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

时间:2017-04-05 15:04:59

标签: c# wpf binding behavior

我有一个自定义行为,它将布尔值作为参数。我试图将它绑定到我的模型中的属性但我无法使其工作。 (我使用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 UserControl,DataContext在代码隐藏中定义如下:

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

我的ViewModel:

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课程:

 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在他博客上的技巧解释{{3}这就是我得到的:

<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>

我已经好几次使用过这个技巧了,我知道它也有效,但在这种情况下却没有。现在我经过几个小时的搜索后仍然坚持这一点,所以非常欢迎任何帮助。

谢谢

1 个答案:

答案 0 :(得分:0)

好的,所以当我调用这个行为时,我认为我的CahierDesCharges为空。因此HasLotPartie无论如何都是假的,所以它没有达到我的活动。所以我只是在AssociatedObject_Loaded方法中移动了我的if()并且它有效。我需要等到GridControl完全加载,因此CahierDesCharges不再为null。 这是我现在的行为类:

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();
    }
}

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