Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/333.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在多个UI线程中共享具有DynamicSource样式的笔_C#_Wpf_Freezable - Fatal编程技术网

C# 在多个UI线程中共享具有DynamicSource样式的笔

C# 在多个UI线程中共享具有DynamicSource样式的笔,c#,wpf,freezable,C#,Wpf,Freezable,我有一个自定义WPF控件,它的依赖属性类型为Pen(用于设置控件内分隔线的样式) 此属性的默认值应为系统颜色——如果使用此默认值,则控件必须在用户更改系统颜色时更新(在Windows设置中) 到目前为止,我已将此默认值指定为默认控件样式的一部分: <Style TargetType="{x:Type my:Control}"> <Setter Property="DividerPen"> <Pen Brush="{DynamicResourc

我有一个自定义WPF控件,它的依赖属性类型为
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>