如何在静态资源上设置依赖属性?

3
我正在尝试解决一个问题,即无法为ConverterParameter指定动态值。请参阅我的其他问题,了解为什么需要将动态值绑定到ConverterParameter - 我不喜欢当前发布的解决方案,因为它们都需要对我的视图模型进行我认为不必要的更改。
为了解决这个问题,我创建了一个自定义转换器,并在该转换器上公开了一个依赖属性:
public class InstanceToBooleanConverter : DependencyObject, IValueConverter
{
    public object Value
    {
        get { return (object)GetValue(ValueProperty); }
        set { SetValue(ValueProperty, value); }
    }

    public static readonly DependencyProperty ValueProperty =
        DependencyProperty.Register("Value", typeof(object), typeof(InstanceToBooleanConverter), null);

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return value != null && value.Equals(Value);
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return value.Equals(true) ? Value : Binding.DoNothing;
    }
}

有没有一种方法可以在我的XAML中使用绑定(或样式设置器,或其他疯狂的方法)来设置这个值?

<ItemsControl ItemsSource="{Binding Properties}">
    <ItemsControl.ItemTemplate>
        <DataTemplate DataType="{x:Type local:SomeClass}">
            <DataTemplate.Resources>
                <!-- I'd like to set Value to the item from ItemsSource -->
                <local:InstanceToBooleanConverter x:Key="converter" Value="{Binding Path=???}" />
            </DataTemplate.Resources>
<!- ... ->

到目前为止,我看到的例子只绑定静态资源。
编辑:
我得到了一些反馈,我的 XAML 只有一个转换器实例。
我可以通过将资源放在我的控件中来解决这个问题。
<ItemsControl ItemsSource="{Binding Properties}">
    <ItemsControl.ItemTemplate>
        <DataTemplate DataType="{x:Type local:SomeClass}">
            <RadioButton Content="{Binding Name}" GroupName="Properties">
                <RadioButton.Resources>
                    <!-- I'd like to set Value to the item from ItemsSource -->
                    <local:InstanceToBooleanConverter x:Key="converter"
                                                      Value="{Binding Path=???}" />
                </RadioButton.Resources>
                <RadioButton.IsChecked>
                    <Binding Path="DataContext.SelectedItem"
                             RelativeSource="{RelativeSource AncestorType={x:Type Window}}"
                             Converter="{StaticResource converter}" />
                </RadioButton.IsChecked>
            </RadioButton>
<!- ... ->

所以这个问题不会因为需要共享转换器的实例而被阻塞 :)
2个回答

1

很遗憾,这不会起作用 - 我以前走过这条路,结果发现ItemsControl中的所有项都共享同一个转换器。我认为这是由于XAML解析器的工作方式造成的。


是的,我可以看出那可能会成为一个问题。不过我注意到如果我将其设置为控件上的资源,那么每个控件都会有一个实例。如果这样更合理的话,我可以修改我的问题。 - Merlyn Morgan-Graham

0

首先,您可以在更高级别的资源字典中指定转换器,并将{{link1:x:Shared}}设置为false。其次,如果您想要像您注释的那样"将值设置为ItemsSource中的项",您只需指定一个空绑定(Value="{Binding}")。


感谢提供 x:Shared 的信息。至于绑定,当我使用 Value="{Binding}" 时,我的依赖属性的 setter 似乎从未被调用过。 - Merlyn Morgan-Graham
依赖属性的设置器不被内部机制使用,它们仅用于代码后台访问。这就是为什么除了SetValue/GetValue调用之外,永远不应该在其中放置任何代码的原因。 - H.B.
关于 setter 没有被调用,你是正确的。如果我从 Value="{Binding}" 改为 Value="{StaticResource someOtherResource}",getter 会返回那个静态资源实例,但 setter 永远不会被调用。但是当我回到 Value="{Binding}",getter 返回 null - Merlyn Morgan-Graham
没关系,绑定毕竟不是一个值。(在某些点上,绑定可能不返回值,因此 GetValue 返回 null - H.B.
(在绑定的某些点可能不会返回值,因此GetValue返回null)。您是指在应用程序启动/ UI创建期间的某些时刻,还是在运行应用程序时的某些时刻?在测试中,我使用了一个DataContext(在构造函数中设置),以确保没有任何空值。我开始认为这个绑定是在编译时发生的,然后进行序列化。 - Merlyn Morgan-Graham
抱歉我没有回复,可能是我不小心忽略了你的评论。绑定确实发生在运行时,但我的分析可能是错误的,我会说这个绑定不会起作用,因为 ValueConverters 没有 DataContext 或者甚至没有可视化树连接。你的来源仅限于 Source 属性,我预计 DataContext(没有明确的来源)、ElementNameRelativeSource 在这里都不会起作用。 - H.B.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接