C# 在多个UI线程中共享具有DynamicSource样式的笔
我有一个自定义WPF控件,它的依赖属性类型为C# 在多个UI线程中共享具有DynamicSource样式的笔,c#,wpf,freezable,C#,Wpf,Freezable,我有一个自定义WPF控件,它的依赖属性类型为Pen(用于设置控件内分隔线的样式) 此属性的默认值应为系统颜色——如果使用此默认值,则控件必须在用户更改系统颜色时更新(在Windows设置中) 到目前为止,我已将此默认值指定为默认控件样式的一部分: <Style TargetType="{x:Type my:Control}"> <Setter Property="DividerPen"> <Pen Brush="{DynamicResourc
Pen
(用于设置控件内分隔线的样式)
此属性的默认值应为系统颜色——如果使用此默认值,则控件必须在用户更改系统颜色时更新(在Windows设置中)
到目前为止,我已将此默认值指定为默认控件样式的一部分:
<Style TargetType="{x:Type my:Control}">
<Setter Property="DividerPen">
<Pen Brush="{DynamicResource {x:Static SystemColors.ActiveBorderBrushKey}}"
Thickness="1"/>
</Setter>
...
</Style>
显然,在
实例中使用动态资源可以防止样式被冻结
到目前为止,我可以想到两种解决方案:
1) 在样式上设置x:Shared=“False”
。每个控件实例都有自己的默认样式副本,因此不必冻结它。但是,该样式还有一些其他的setter(包括一个非平凡的模板),因此我更希望这些setter可以在我的控件的多个实例中共享
2) 将类型为Pen
的属性拆分为笔刷、厚度、短划线样式等单独的属性。这将导致{DynamicResource}
直接用于样式的setter,从而允许冻结样式。(虽然我不确定某个样式何时可以自由使用的确切细节)
这个解决方案并不可取,因为我有多个Pen类型的属性,每个属性都有很多用户可能想要自定义的属性。另外,我希望修复此异常,而不在控件的公共API中引入破坏性的更改
还有其他想法吗?是否有其他方法为DividerPen属性指定此类默认值
由于我所说的多UI线程似乎有些混淆,下面是在其自己的线程中打开新窗口的代码:
public void OpenNewWindow()
{
Thread t = new Thread(new ThreadStart(Run));
t.SetApartmentState(ApartmentState.STA);
t.Start();
}
void Run()
{
var window = new Window();
window.Content = new MyUserControl();
window.Show();
// just for test purposes; a real multithreaded WPF app needs logic to shutdown the dispatcher when the window is closed
Dispatcher.Run();
}
我想我需要更多的代码来准确理解你在做什么 我们不知道你是如何定义你的线程的,也不知道你陷入了什么样的困境,但是这里有一个例子,我希望你能找到解决问题的方法 这是应用程序资源字典:
<SolidColorBrush x:Key="redBrushKey" Color="Red"/>
<Pen x:Key="penKey" Brush="{DynamicResource redBrushKey}"/>
<Style TargetType="Rectangle">
<Setter Property="Height" Value="50"/>
<Setter Property="Width" Value="50"/>
<Setter Property="Fill">
<Setter.Value>
<DrawingBrush>
<DrawingBrush.Drawing>
<GeometryDrawing Brush="Yellow" Pen="{StaticResource penKey}">
<GeometryDrawing.Geometry>
<RectangleGeometry Rect="0,0,10,10"/>
</GeometryDrawing.Geometry>
</GeometryDrawing>
</DrawingBrush.Drawing>
</DrawingBrush>
</Setter.Value>
</Setter>
</Style>
这是我的主窗口:
<StackPanel>
<Button Click="OnStartNewWindow">start new window</Button>
</StackPanel>
启动新窗口
我只需单击主窗口中的按钮,新窗口就会打开,其中有一个带有红色边框的矩形,因为红色是我为画笔指定的颜色
对我来说一切都很好。如果要在ViewModel内运行新窗口,请使用this.Dispatcher.Invoke的insead.Current.Dispatcher.Invoke方法
我在窗口中添加了代码中的堆栈面板,但它也可以与xaml一起使用。通过在代码中调用Freeze()或在xaml中调用PresentationOptions:Freeze=“true”来冻结Freezables。像那样冻结你所有的画笔,颜色,任何可自由化的东西,你应该做得很好,但是笔不能冻结,因为它有一个动态的颜色。我需要一些解决方案,在系统颜色改变时创建新的冻结笔。但是我如何从一个样式中引用冻结笔的最新版本呢?好的,我明白了,让我给你举一个例子。我在自己的线程上运行第二个窗口(在另一个调度程序中)-我已经在问题中添加了线程开始代码。
private void OnStartNewWindow(object sender, RoutedEventArgs args)
{
// Create and show the Window
Window tempWindow = new Window();
Rectangle rect = new Rectangle();
StackPanel stackPanel = new StackPanel();
stackPanel.Children.Add(rect);
tempWindow.Content = stackPanel;
tempWindow.Show();
}
<StackPanel>
<Button Click="OnStartNewWindow">start new window</Button>
</StackPanel>