【问题标题】:WPF: Not able to set color in resource through bindingWPF:无法通过绑定在资源中设置颜色
【发布时间】:2015-05-09 19:01:00
【问题描述】:

我们在应用程序中以 xaml 资源的形式拥有不同的图标,如下所示:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<DrawingBrush x:Key="My_Icon">
    <DrawingBrush.Drawing>
        <GeometryDrawing Brush="Gray"> <!--I want to set this Brush here using binding-->
            <GeometryDrawing.Geometry>
                <GeometryGroup>
                    <EllipseGeometry Center="50,50" RadiusX="45" RadiusY="20" />
                    <EllipseGeometry Center="50,50" RadiusX="20" RadiusY="45" />
                </GeometryGroup>
            </GeometryDrawing.Geometry>
        </GeometryDrawing>
    </DrawingBrush.Drawing>
</DrawingBrush>

而我们在另一个xaml文件中使用这些资源(在后面的代码中加载这个资源,参考下面的代码)

public partial class Window2 : Window
{
    public Window2()
    {
        InitializeComponent();

        var resource = Application.Current.FindResource("My_Icon");
        this.MyBrush = resource as DrawingBrush;

        NewBrush = Brushes.Blue;

        this.DataContext = this;
    }

    private DrawingBrush _myBrush;

    public DrawingBrush MyBrush
    {
        get { return _myBrush; }
        set { _myBrush = value; }
    }

    private Brush _newBrush;

    public Brush NewBrush
    {
        get { return _newBrush; }
        set { _newBrush = value; }
    }
}

问题是,我无法使用绑定设置图标颜色(在资源代码中,第一个代码 sn-p),其属性位于 ViewModel 中(MyBrush 属性在本例中位于 Window2 代码后面)

我尝试在资源文件中使用以下代码:

<GeometryDrawing Brush="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=Rectangle}, Path=NewBrush}">

但这不起作用。我可能在这里遗漏了什么。

【问题讨论】:

  • 您是否包含资源字典?
  • 是的。我做到了。这是我设置的灰色工作样本。我要做的就是用绑定设置这个颜色。
  • 我不确定您要在这里完成什么。从您的最后一个代码 sn-p 来看,您正在尝试将 GeomertyDrawing.Brush 属性绑定到 Window2.MyBrush 属性,该属性包含 &lt;DrawingBrush x:Key="My_Icon"&gt;",而后者又是 GeometryDrawing 的父级 - 这会导致循环依赖和肯定会导致异常...
  • 我刚刚编辑了这个问题。为错误道歉
  • 你能添加一个示例项目吗?

标签: c# .net wpf xaml


【解决方案1】:

我想出了两种方法来解决您的问题。

解决方案 I(我认为更好)

放弃你的代码隐藏方法,将你的资源字典直接导入到你的窗口资源中,并使用StaticResourceExtension 来引用资源:

<Window.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="TheNameOfYourDictionary.xaml"/>
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</Window.Resources>
...
<Rectangle Fill="{StaticResource My_Icon}"/>

当您这样做并使用 AncestorType=local:Window2 时,您的绑定应该可以工作(尽管在当前形状中,NewBrush 属性的后续更改不会反映在绘图中 - 请参阅此答案末尾的列表)。请注意,必须使用{StaticResource My_Icon} 而不是{Binding MyBrush}

解决方案二

在您的代码隐藏中设置绑定:

var resource = Application.Current.FindResource("My_Icon");
this.MyBrush = resource as DrawingBrush;

NewBrush = Brushes.Blue;

BindingOperations.SetBinding(MyBrush.Drawing, GeometryDrawing.BrushProperty,
    new Binding { Path = new PropertyPath("NewBrush"), Source = this });

请注意,为了使此(或第一个解决方案)起作用,应满足以下条件之一:

  1. NewBrush 在绑定设置之前设置(在第一个解决方案的情况下设置DataContext 之前)
  2. Window2 实现 INotifyPropertyChangedPropertyChanged 事件在 NewBrush 设置后引发
  3. NewBrush 是一个依赖属性

【讨论】:

  • 感谢您的回答,我会选择第二种方法,因为我们在运行时针对不同的条件加载不同的资源(不同实体类型的不同图标)。所以我可能每次都指的是一个单独的资源。您认为我仍然可以使用您提供的解决方案 I 做到这一点。另外,我是否应该对资源中的绘图进行空检查,可能是针对某些我没有绘图的资源。如果是,如何进行空检查。
  • 我面临一个小问题:如果我取消资源中的 Brush 绑定代码,我会收到错误消息。一世。 e.如果我将 更改为 我收到此错误:“无法在对象 'System.Windows 上设置属性。 Media.GeometryDrawing',因为它处于只读状态。”
  • @DotnetRocks 关于您的第一条评论 - 如果您的意思是根据某些条件动态引用不同的资源,那么可以在 XAML 中完成 - 请参阅 Styling triggers。至于第二个问题,它的出现显然是因为除非您在GeometryDrawing 上设置绑定,否则如前所述,它会以“只读”状态返回。一种解决方法是使用通过Clone() 方法获得的DrawingBrush 的可修改副本,即MyBrush = ((DrawingBrush)resource).Clone();
猜你喜欢
  • 1970-01-01
  • 2011-01-09
  • 1970-01-01
  • 2011-09-12
  • 1970-01-01
  • 2016-01-12
  • 2012-11-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多