【问题标题】:How to choose brush in XAML based on bindingXAML中如何基于绑定选择画笔
【发布时间】:2012-04-08 11:19:56
【问题描述】:

我在 Application.xaml 中定义了数百个画笔。这些是项目中多个用户控件的共享资源。它们都有图案键:ch_YSD、ch_HJU、ch_IYO...

我尝试在数据模板中使用这些画笔。在数据模板中,我可以访问画笔键的可变部分,即在数据模板中,我可以将 YSD、HJU、IYO 等作为字符串。

如何从 xaml 绑定到特定的画笔资源?

目前我有这样的解决方案:在样式中使用数据触发器根据绑定的字符串(键的可变部分)将所需的属性设置为指定的画笔。 我对这个解决方案不满意,因为 Application.xaml 中的画笔列表会经常增加。

我不确定是否应该使用后面的代码,因为我想在 Application.xaml 中使用共享资源的内存节省优势。

【问题讨论】:

    标签: .net wpf xaml binding resources


    【解决方案1】:

    这是一种看似简单但实际上没有完美解决方案的任务(或者我没有找到)。第一种方法是使用值转换器。但它不起作用!我们需要设置转换器无法正确完成的资源引用。所以,我认为正确的方法是依附行为。但是您应该了解限制:只能将资源应用于一个属性。也许您可以根据您的要求避免此限制。

    附加行为允许您将具有指定名称的资源引用到指定的依赖属性:

    public static class BrushResourceKeyBehavior
    {
        #region ResourceKey Property
    
        public static readonly DependencyProperty ResourceKeyProperty = DependencyProperty.RegisterAttached(
            "ResourceKey", typeof(object), typeof(BrushResourceKeyBehavior),
            new FrameworkPropertyMetadata(OnResourceKeyChanged));
    
        public static object GetResourceKey(DependencyObject dependencyObject)
        {
            return dependencyObject.GetValue(ResourceKeyProperty);
        }
    
        public static void SetSource(DependencyObject dependencyObject, object value)
        {
            dependencyObject.SetValue(ResourceKeyProperty, value);
        }
    
        #endregion
    
        #region TargetProperty Property
    
        public static readonly DependencyProperty TargetPropertyProperty = DependencyProperty.RegisterAttached(
            "TargetProperty", typeof(DependencyProperty), typeof(BrushResourceKeyBehavior),
            new FrameworkPropertyMetadata(OnTargetPropertyChanged));
    
        public static DependencyProperty GetTargetProperty(DependencyObject dependencyObject)
        {
            return (DependencyProperty)dependencyObject.GetValue(TargetPropertyProperty);
        }
    
        public static void SetTargetProperty(DependencyObject dependencyObject, DependencyProperty value)
        {
            dependencyObject.SetValue(TargetPropertyProperty, value);
        }
    
        #endregion
    
        private static void OnResourceKeyChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
        {
            var targetProperty = GetTargetProperty(dependencyObject);
            if (targetProperty != null)
            {
                if (e.NewValue == null)
                {
                    dependencyObject.ClearValue(targetProperty);
                }
                else
                {
                    SetResourceReference(dependencyObject, targetProperty);
                }
            }
        }
    
        private static void OnTargetPropertyChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
        {
            var oldValue = e.OldValue as DependencyProperty;
            var newValue = e.NewValue as DependencyProperty;
    
            if (oldValue != null)
            {
                dependencyObject.ClearValue(oldValue);
            }
    
            if (newValue != null)
            {
                SetResourceReference(dependencyObject, newValue);
            }
        }
    
        private static void SetResourceReference(DependencyObject dependencyObject, DependencyProperty targetProperty)
        {
            var fe = dependencyObject as FrameworkElement;
            if (fe != null)
            {
                fe.SetResourceReference(targetProperty, String.Format("ch_{0}", GetResourceKey(fe)));
            }
            else
            {
                var fce = dependencyObject as FrameworkContentElement;
                if (fce != null)
                {
                    fce.SetResourceReference(targetProperty, String.Format("ch_{0}", GetResourceKey(fce)));
                }
            }
        }
    }
    

    行为可以在 XAML 中使用,如下所示:

    <ItemsControl>
        <Border local:BrushResourceKeyBehavior.Source="YSD"
                local:BrushResourceKeyBehavior.TargetProperty="Border.Background"
                Height="20"/>
        <Border local:BrushResourceKeyBehavior.Source="HJU"
                local:BrushResourceKeyBehavior.TargetProperty="Border.Background"
                Height="20"/>
        <Border local:BrushResourceKeyBehavior.Source="IYO"
                local:BrushResourceKeyBehavior.TargetProperty="Border.Background"
                Height="20"/>
    </ItemsControl>
    

    上面的代码相当于:

    <ItemsControl>
        <Border Background="{DynamicResource ch_YSD}"
                Height="20"/>
        <Border Background="{DynamicResource ch_HJU}"
                Height="20"/>
        <Border Background="{DynamicResource ch_IYO}"
                Height="20"/>
    </ItemsControl>
    

    【讨论】:

    • 非常感谢这个优秀的例子,你拯救了我的一天! :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-20
    • 2017-12-22
    相关资源
    最近更新 更多