WPF 绑定到行为 属性 不起作用

WPF Binding to behavior property is not working

我有一个将布尔值作为参数的自定义行为。我试图将它绑定到我模型中的 属性 但我无法让它工作。 (我正在使用 DevExpress)

<dxg:GridControl
        x:Name="dgArticles"
        Grid.Row="1"
        AutoGenerateColumns="None"
        ItemsSource="{Binding Path=Articles, Mode=TwoWay}">

        <dxmvvm:Interaction.Behaviors>
            <util:ExpandAllBehavior HasLotPartie="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}, Path=DataContext.CahierDesCharges.HasLotPartie }" />
        </dxmvvm:Interaction.Behaviors>


    </dxg:GridControl

这是一个 WPF 用户控件,DataContext 在代码隐藏中定义如下:

public partial class GridView : UserControl
{
    public GridView(ArticleViewModel a)
    {
        InitializeComponent();
        this.DataContext = a;          
    }        
}

我的视图模型:

public class ArticleViewModel : INotifyPropertyChanged
{

    private Cahier cahierDesCharges;
    public Cahier CahierDesCharges { get { return cahierDesCharges; } set { } }

    private ObservableCollection<Article> articles;
    public ObservableCollection<Article> Articles
    {
        get { return articles; }
        set { articles = value; OnPropertyChanged("articles"); }
    }

    public ArticleViewModel() { }

    public ArticleViewModel(Cahier c)
    {
        this.cahierDesCharges = c;
        this.articles = CahierDesCharges.Articles;
    }

    private void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this,
                new System.ComponentModel.PropertyChangedEventArgs(propertyName));

    }
}

CahierDesCharges Class:

 public class Cahier : INotifyPropertyChanged
{
    public bool HasLotPartie { get; set; }

    private ObservableCollection<Article> articles;
    public ObservableCollection<Article> Articles
    {
        get { return articles; }
        set { articles = value; OnPropertyChanged("articles"); }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public Cahier() { }
    private void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this,
                new System.ComponentModel.PropertyChangedEventArgs(propertyName));
        Console.WriteLine(propertyName);
    }
}

行为:

public class ExpandAllBehavior : Behavior<GridControl>
{
    public static readonly DependencyProperty HasLotPartieProperty =
    DependencyProperty.Register("HasLotPartie", typeof(Boolean), typeof(ExpandAllBehavior));
    public bool HasLotPartie
    {
        get { return (bool)GetValue(HasLotPartieProperty); }
        set { SetValue(HasLotPartieProperty, value); }
    }

    protected override void OnAttached()
    {
        if (HasLotPartie)
        {
            base.OnAttached();

            this.AssociatedObject.CustomRowFilter += AssociatedObject_Loaded;
        }

    }

    void AssociatedObject_Loaded(object sender, EventArgs e)
    {
        int dataRowCount = AssociatedObject.VisibleRowCount;
        for (int rowHandle = 0; rowHandle < dataRowCount; rowHandle++)
            AssociatedObject.ExpandMasterRow(rowHandle);


    }



    protected override void OnDetaching()
    {
        base.OnDetaching();
    }
}

我在另一个地方使用了 "{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}, Path=DataContext.CahierDesCharges.HasLotPartie }" 行,我知道它可以正常工作。在下面的示例中,它工作得很好:

 <dxg:GridControl.View>
            <dxg:TableView
                AllowScrollAnimation="True"
                EnableImmediatePosting="True"
                IsDetailButtonVisibleBinding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}, Path=DataContext.CahierDesCharges.HasLotPartie }"
                Name="view"
                ShowGroupedColumns="False"
                ShowGroupPanel="False"
                UseLightweightTemplates="None" />
        </dxg:GridControl.View>

如果我手动将该值设置为 true,则行为正常:<util:ExpandAllBehavior HasLotPartie="True" /> 所以我认为可能是 DadaContext 不是继承的,我使用了 Thomas Levesque 在他的博客上解释的技巧 here 这就是我得到的:

<dxg:GridControl.Resources>             
            <util:BindingProxy x:Key="proxy" Data="{Binding}" />
        </dxg:GridControl.Resources>
        <dxmvvm:Interaction.Behaviors>
            <util:ExpandAllBehavior HasLotPartie="{Binding Data.CahierDesCharges.HasLotPartie, Source={StaticResource proxy}}" />
        </dxmvvm:Interaction.Behaviors>

这个技巧我用过好几次,我知道它也能用,但在这种情况下不行。经过几个小时的搜索,现在我仍然坚持这个,所以非常欢迎任何帮助。

谢谢

好的,所以我认为在调用行为时我的 CahierDesCharges 为空。因此 HasLotPartie 无论如何都是错误的,所以它没有到达我的事件。所以我只是在 AssociatedObject_Loaded 方法中移动了我的 if() 并且它起作用了。我需要等到 GridControl 完全加载后,CahierDesCharges 才不再为空。 这是我现在的行为 class:

public class ExpandAllBehavior : Behavior<GridControl>
{
    public static readonly DependencyProperty HasLotPartieProperty =
    DependencyProperty.Register("HasLotPartie", typeof(bool), typeof(ExpandAllBehavior));

    public bool HasLotPartie
    {
        get { return (bool)GetValue(HasLotPartieProperty); }
        set { SetValue(HasLotPartieProperty, value); }
    }

    protected override void OnAttached()
    {
        base.OnAttached();
        this.AssociatedObject.Loaded += AssociatedObject_Loaded; //Apllied after GridControl is fully loaded.
        this.AssociatedObject.CustomRowFilter += AssociatedObject_Loaded; //Applied after filtering on Rows
    }

    void AssociatedObject_Loaded(object sender, EventArgs e)
    {
        if (HasLotPartie)
        {
            int dataRowCount = AssociatedObject.VisibleRowCount;
            for (int rowHandle = 0; rowHandle < dataRowCount; rowHandle++)
                AssociatedObject.ExpandMasterRow(rowHandle);
        }
    }



    protected override void OnDetaching()
    {
        base.OnDetaching();
    }
}

现在,当 HasLotPartie 为真时,我的 MasterDetails 总是展开,这是想要的效果。 一如既往,我一直专注于复杂的事情,而解决方案却很简单。