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 总是展开,这是想要的效果。
一如既往,我一直专注于复杂的事情,而解决方案却很简单。
我有一个将布尔值作为参数的自定义行为。我试图将它绑定到我模型中的 属性 但我无法让它工作。 (我正在使用 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 总是展开,这是想要的效果。
一如既往,我一直专注于复杂的事情,而解决方案却很简单。