gpt4 book ai didi

c# - 如何处理包含列表的 WPF 用户控件中的嵌套绑定(bind)?

转载 作者:太空宇宙 更新时间:2023-11-03 15:07:57 24 4
gpt4 key购买 nike

我正在尝试在 WPF 中创建一个包含内容集合的用户控件,并努力让绑定(bind)在子元素上正常工作。我已经看过这个例子,但我的嵌套比这个更深一层,所以这个解决方案没有帮助:Data Binding in WPF User Controls

这是我的用户控件:

<UserControl x:Class="BindingTest.MyList"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300"
x:Name="uc">
<Grid>
<ListView Grid.Row="1" ItemsSource="{Binding Items, ElementName=uc}">
<ListView.ItemTemplate>
<DataTemplate>
<Label Content="{Binding Text}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</UserControl>

以及代码隐藏:

[ContentProperty("Items")]
public partial class MyList : UserControl {
public MyList() {
InitializeComponent();
}

public ObservableCollection<MyItem> Items { get; set; } = new ObservableCollection<MyItem>();
}

public class MyItem : DependencyObject {
public string Text {
get {
return (string)this.GetValue(TextProperty);
}
set {
this.SetValue(TextProperty, value);
}
}
public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(MyItem), new PropertyMetadata());
}

然后是我如何在应用程序中使用它:

<Window x:Class="BindingTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:BindingTest"
Title="MainWindow" Height="350" Width="525"
DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>

<TextBox Grid.Row="0" Text="{Binding Val1, Mode=TwoWay}" />

<local:MyList Grid.Row="1">
<local:MyItem Text="{Binding Val1}" />
<local:MyItem Text="Two" />
<local:MyItem Text="Three" />
</local:MyList>

<ListView Grid.Row="2">
<ListViewItem Content="{Binding Val1}" />
<ListViewItem Content="Bravo" />
<ListViewItem Content="Charlie" />
</ListView>
</Grid>
</Window>

最后是我的窗口:

public partial class MainWindow : Window, INotifyPropertyChanged {
public MainWindow() {
InitializeComponent();
}

string _val1 = "Foo";
public string Val1 {
get { return _val1; }
set {
_val1 = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Val1"));
}
}

public event PropertyChangedEventHandler PropertyChanged;
}

我遇到的问题是,用户控件中的第一个“MyItem”最终显示空白文本,而库存控件中的第一个 ListViewItem 则如您所料显示 Foo。

我理解这是因为在 MyList 控件中,DataTemplate 为集合中的每个项目切换 DataContext,但无论我在绑定(bind)表达式中尝试什么,无论是在窗口还是在用户控件中,我都无法得到它正确绑定(bind)到窗口上的 Val1。

我做错了什么?

最佳答案

您是正确的,MyItem 对象的 DataContext 没有要绑定(bind)到的 Val1 值,这就是绑定(bind)中断的原因。这与您在 DataGrids 中常见的问题相同,其中内部项 (MyItem) 的上下文设置为 ItemSource 的一个元素(在您的例子中为 ObservableCollection Items)。

我总是解决这个问题的方法是在 DataGrid 或 Control 的资源中包含一个对象,该对象引用了控件的 DataContext。这样您就可以将该对象作为 StaticResource 绑定(bind),而不必更改控件中的 XAML。

保存数据上下文的类:

 public class BindingProxy : Freezable
{
protected override Freezable CreateInstanceCore() { return new BindingProxy(); }

public static readonly DependencyProperty ContextProperty =
DependencyProperty.Register("Context", typeof(object), typeof(BindingProxy), new UIPropertyMetadata(null));

public object Context
{
get { return (object)GetValue(ContextProperty); }
set { SetValue(ContextProperty, value); }
}
}

然后将 BindingProxy 的一个实例添加到您的 MyList 的资源中,并将 Context 属性绑定(bind)到 MyList 的绑定(bind)。然后您可以按名称将 BindingProxy 作为 StaticResource 绑定(bind)。路径是资源的上下文属性,然后是您要绑定(bind)到的值的正常路径。

<local:MyList Grid.Row="1">
<local:MyList.Resources>
<local:BindingProxy x:Key="VMProxy" Context="{Binding}"/>
</local:MyList.Resources>
<local:MyItem Text="{Binding Path=Context.Val1, Source={StaticResource VMProxy}}"/>
<local:MyItem Text="Two" />
<local:MyItem Text="Three" />
</local:MyList>

我用您拥有的控件和窗口代码对其进行了测试,效果非常好。我不能完全相信这个解决方案,因为我是在 SO 上找到它的,但就我的生活而言,我找不到包含这个 DataGrids 解决方案的旧答案。

关于c# - 如何处理包含列表的 WPF 用户控件中的嵌套绑定(bind)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42535205/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com