附加属性未触发 IMultiValueConverter

Posted

技术标签:

【中文标题】附加属性未触发 IMultiValueConverter【英文标题】:Attached Property not triggering IMultiValueConverter 【发布时间】:2015-03-08 14:52:27 【问题描述】:

下面是我的 DataGrid,它带有一些与弹出控件相关联的附加属性。 ComboBox 由枚举填充。

    <DataGrid Name="GenericDataGrid" 
              helpers:SearchBehaviours.SearchValue="Binding ElementName=FindTextbox, Path=Text, UpdateSourceTrigger=PropertyChanged"
              helpers:SearchBehaviours.IsFindPopupOpen="Binding ElementName=PopupFind, Path=IsOpen, UpdateSourceTrigger=PropertyChanged"
              helpers:SearchBehaviours.SearchableItems="Binding ElementName=ComboSearchableItems, Path=SelectedValue, UpdateSourceTrigger=PropertyChanged" >
    </DataGrid>

    <Popup x:Name="PopupFind">
        <TextBox x:Name="FindTextbox" />
        <ComboBox x:Name="ComboSearchableItems" 
            ItemsSource="Binding Source=helpers:Enumeration x:Type helpers:SearchItems"
            DisplayMemberPath="Description"
            SelectedValue="x:Static helpers:SearchItems.AllItems"
            SelectedValuePath="Value" />
    </Popup>

这是处理行为的类:

class SearchBehaviours

    // Using a DependencyProperty as the backing store for IsTextMatch.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty IsTextMatchProperty =
        DependencyProperty.RegisterAttached("IsTextMatch", typeof(bool), typeof(SearchBehaviours), new UIPropertyMetadata(false));

    public static bool GetIsTextMatch(DependencyObject obj)
    
        return (bool)obj.GetValue(IsTextMatchProperty);
    

    public static void SetIsTextMatch(DependencyObject obj, bool value)
    
        obj.SetValue(IsTextMatchProperty, value);
    

    public static readonly DependencyProperty SearchValueProperty =
        DependencyProperty.RegisterAttached("SearchValue", typeof(string), typeof(SearchBehaviours), new FrameworkPropertyMetadata(string.Empty, FrameworkPropertyMetadataOptions.Inherits));

    public static string GetSearchValue(DependencyObject obj)
    
        return (string)obj.GetValue(SearchValueProperty);
    

    public static void SetSearchValue(DependencyObject obj, string value)
    
        obj.SetValue(SearchValueProperty, value);
    


    public static readonly DependencyProperty IsFindPopupOpenProperty =
        DependencyProperty.RegisterAttached("IsFindPopupOpen", typeof(bool), typeof(SearchBehaviours),
        new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.Inherits));

    public static bool GetIsFindPopupOpen(DependencyObject obj)
    
        return (bool)obj.GetValue(IsFindPopupOpenProperty);
    

    public static void SetIsFindPopupOpen(DependencyObject obj, bool value)
    
        obj.SetValue(IsFindPopupOpenProperty, value);
    


    public static readonly DependencyProperty SearchableItemsProperty =
        DependencyProperty.RegisterAttached("SearchableItems", typeof(SearchItems), typeof(SearchBehaviours), new PropertyMetadata(SearchItems.AllItems));

    public static SearchItems GetSearchableItems(DependencyObject obj)
    
        return (SearchItems)obj.GetValue(SearchableItemsProperty);
    

    public static void SetSearchableItems(DependencyObject obj, SearchItems value)
    
        obj.SetValue(SearchableItemsProperty, value);
    

问题出在下面的 IMultiValueConverter

<Style TargetType="x:Type DataGridCell" x:Key="textCellStyle" >
    <Setter Property="helpers:SearchBehaviours.IsTextMatch">
        <Setter.Value>
            <MultiBinding Converter="StaticResource SearchValueConverter" FallbackValue="False">
                <Binding Path="Content.Text" RelativeSource="RelativeSource Self" />
                <Binding Path="(helpers:SearchBehaviours.SearchValue)" RelativeSource="RelativeSource Self" />
                <Binding Path="(helpers:SearchBehaviours.IsFindPopupOpen)" RelativeSource="RelativeSource Self"/>
                <Binding Path="(helpers:SearchBehaviours.SearchableItems)" RelativeSource="RelativeSource Self"/>
                <Binding />
                <Binding RelativeSource="x:Static RelativeSource.Self"/>
            </MultiBinding>
        </Setter.Value>
    </Setter>

    <Style.Triggers>
        <Trigger Property="helpers:SearchBehaviours.IsTextMatch" Value="True">
            <Setter Property="Background" Value="DarkOrange" />
            <Setter Property="Foreground" Value="White"/>
        </Trigger>
    </Style.Triggers>
</Style>

当弹出窗口打开和关闭时,它会触发 IMultiValueConverter。 它在文本框文本更改时触发。 但是,如果 ComboBox 中的 SelectedValue 发生更改,则不会触发。 下面是当前触发时输出的相当简单的转换器。

public class SearchValueConverter : IMultiValueConverter

    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    
        Console.WriteLine("Triggered");
        return false;
    

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
    
        return null;
    

[编辑]

public enum SearchItems

    [Description("All Items")]
    AllItems,
    [Description("Selected Items")]
    SelectedItems

[结束编辑]

有人可以解决问题吗?

【问题讨论】:

我在SearchBehaviours 类中看不到定义IsTextMatch 属性。我想是 bool 属性,但您的 SearchValueConverter 不会在 Convert 方法中返回任何值。它应该返回布尔值。由于这个原因,触发器永远不会引发。 嗨@user2250152,我已经添加了 IsTextMatch 属性,你的位置只是一个 bool 属性。还添加了返回值,那应该是一个错字。还添加了枚举,默认情况下,组合框设置为 AllItems,当我选择 SelectedItems 时,我希望转换器触发,但这不会发生。 您可以尝试在SetSearchableItems 方法上放置一个断点,以检查组合框选择更改时附加的属性设置器是否被触发。这至少会告诉您绑定是否有效。 【参考方案1】:

更改DataGridCell Style代码如下:

<Style TargetType="x:Type DataGridCell">
        <Setter Property="local:SearchBehaviours.IsTextMatch">
            <Setter.Value>
                <MultiBinding Converter="StaticResource SearchValueConverter" FallbackValue="False">
                    <Binding Path="Content.Text" RelativeSource="RelativeSource Self" />
                    <Binding Path="(local:SearchBehaviours.SearchValue)" RelativeSource="RelativeSource Mode=FindAncestor,AncestorType=x:Type DataGrid" />
                    <Binding Path="(local:SearchBehaviours.IsFindPopupOpen)" RelativeSource="RelativeSource Mode=FindAncestor,AncestorType=x:Type DataGrid"/>
                    <Binding Path="(local:SearchBehaviours.SearchableItems)" RelativeSource="RelativeSource Mode=FindAncestor,AncestorType=x:Type DataGrid"/>
                    <Binding />
                    <Binding RelativeSource="x:Static RelativeSource.Self"/>
                </MultiBinding>
            </Setter.Value>
        </Setter>

        <Style.Triggers>
            <Trigger Property="local:SearchBehaviours.IsTextMatch" Value="True">
                <Setter Property="Background" Value="DarkOrange" />
                <Setter Property="Foreground" Value="White"/>
            </Trigger>
        </Style.Triggers>
    </Style>

您将 DataGridCell 的所有附加属性传递给未分配的 MultiBinding Converter。为了解决此问题,您必须将 DataGrid 的附加属性传递给 MultiBindingConverter。

UPDATE :

你也可以像这样使用ComboBox

<ComboBox x:Name="ComboSearchableItems"/>

& 像这样通过代码将 ItemSource 分配给它:

ComboSearchableItems.ItemsSource = Enum.GetValues(typeof(SearchItems));

如果您只想使用XAML 进行绑定,请参考this link

【讨论】:

谢谢你会试一试 嗨,Amol,这在一定程度上有效。不过我有几个问题。为什么前两个属性可以正常工作而第三个不能?另一件事是 DataGrid 是虚拟化的,并且行被回收,这意味着一个单元格放弃其祖先并引发错误: System.Windows.Data 警告:4:找不到与引用'RelativeSource FindAncestor,AncestorType ='System. Windows.Controls.DataGrid' 我的意思是说我也想保持回收。 因为弹出窗口不在您窗口的VisualTree 中。它没有任何父母。 Popup 本身是 TextBox 和 ComboBox 的父级。 它正在工作,因为您已将弹出窗口子属性绑定到附加属性。在您的情况下,附加属性是您用于获取弹出值的媒介。在这种情况下很好......【参考方案2】:

使用 WPF 检查器检查您绑定到控件的内容。

enter link description here

【讨论】:

以上是关于附加属性未触发 IMultiValueConverter的主要内容,如果未能解决你的问题,请参考以下文章

具有未在模型中定义的附加属性的 NSManagedObject 子类

附加属性未更新它绑定到的值 (MVVM)

未收到意向附加费

UIAlertController 上的 UITapGestureRecognizer 未触发

单击处理程序未附加

OnTouch MotionEvent 动作移动未触发