wpf 数据绑定到嵌套属性?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/27731370/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Data Binding to Nested Properties?
提问by baris1892
I'm pretty new to WPF and XAML and now I'm stuck with data binding for days! I just wanted to bind some nested properties to a TextBox and ListView (via XAML), but I'm doing it wrong. Here's my Sample Code:
我对 WPF 和 XAML 还很陌生,现在我被数据绑定困了好几天!我只是想将一些嵌套属性绑定到 TextBox 和 ListView(通过 XAML),但我做错了。这是我的示例代码:
MainWindow.xaml.cs
主窗口.xaml.cs
namespace CounterTestNestedDataBinding
{
public partial class MainWindow : Window
{
public MyModel MyModel { get; set; }
public MainWindow()
{
InitializeComponent();
MyModel = new MyModel { MyCounter = new Counter() };
}
private void Button_Click(object sender, RoutedEventArgs e)
{
MyModel.MyCounter.incrementCounter();
}
}
}
MyModel.cs
我的模型.cs
namespace CounterTestNestedDataBinding
{
public class MyModel : INotifyPropertyChanged
{
public Counter _myCounter;
public Counter MyCounter
{
get { return _myCounter; }
set
{
_myCounter = value;
NotifyPropertyChanged("MyCounter");
}
}
// some other members and properties ...
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(string property)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
}
}
}
Counter.cs
计数器.cs
namespace CounterTestNestedDataBinding
{
public class Counter : INotifyPropertyChanged
{
#region Members
private int _currentNumber;
private ObservableCollection<int> _historyList;
#endregion
#region Constructor
public Counter()
{
_currentNumber = 0;
_historyList = new ObservableCollection<int>();
}
#endregion
#region Properties
public int CurrentNumber
{
get { return _currentNumber; }
set
{
_currentNumber = value;
NotifyPropertyChanged("CurrentNumber");
}
}
public ObservableCollection<int> HistoryList
{
get { return _historyList; }
set
{
_historyList = value;
NotifyPropertyChanged("HistoryList");
}
}
#endregion
public void incrementCounter()
{
HistoryList.Add(CurrentNumber);
CurrentNumber++;
}
public override string ToString()
{
return string.Format("CurrentNumber: {0}, HistoryList: {1}", _currentNumber, String.Join(",", _historyList));
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(string property)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
}
}
}
MainWindow.xaml
主窗口.xaml
<Window x:Class="CounterTestNestedDataBinding.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:counterTestNestedDataBinding="clr-namespace:CounterTestNestedDataBinding"
Title="MainWindow" Height="350" Width="200" ResizeMode="NoResize" WindowStartupLocation="CenterScreen"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
>
<StackPanel Orientation="Vertical">
<TextBox x:Name="TextBoxCounterCurrent" Text="{Binding MyModel.MyCounter.CurrentNumber}"/>
<Button Content="Button" Click="Button_Click"/>
<ListView x:Name="ListViewCounterHistory" Height="75" ItemsSource="{Binding MyModel.MyCounter.HistoryList}"></ListView>
</StackPanel>
</Window>
My questions:
我的问题:
How can I bind nested properties? Is it possible? Why does something like
Text="{Binding MyModel.MyCounter.CurrentNumber}"not work?
Is the "DataContext" set correct in the XAML?
如何绑定嵌套属性?是否可以?为什么像
Text="{Binding MyModel.MyCounter.CurrentNumber}"不行?
XAML 中的“DataContext”设置是否正确?
采纳答案by idursun
Set your data context in the constructor like this:
在构造函数中设置数据上下文,如下所示:
public MainWindow()
{
InitializeComponent();
MyModel = new MyModel { MyCounter = new Counter() };
this.DataContext = MyModel;
}
and then of course the path to your data changes because the data that you are binding is under MyModel. Your bindings should be changed as follows:
然后当然数据的路径会发生变化,因为您绑定的数据在 MyModel 下。您的绑定应更改如下:
<StackPanel Orientation="Vertical">
<TextBox x:Name="TextBoxCounterCurrent" Text="{Binding MyCounter.CurrentNumber}"/>
<Button Content="Button" Click="Button_Click"/>
<ListView x:Name="ListViewCounterHistory" Height="75" ItemsSource="{Binding MyCounter.HistoryList}"></ListView>
</StackPanel>
EDIT:
编辑:
This is how you do it by using XAML.
这就是您使用 XAML 执行此操作的方式。
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication1"
xmlns:system="clr-namespace:System;assembly=mscorlib"
Title="MainWindow" Height="350" Width="525" >
<Window.Resources>
<local:MyModel x:Key="myModal" />
</Window.Resources>
<StackPanel Orientation="Vertical" DataContext="{StaticResource myModal}">
<TextBox x:Name="TextBoxCounterCurrent" Text="{Binding MyCounter.CurrentNumber}"/>
<Button Content="Button" Click="Button_Click"/>
<ListView x:Name="ListViewCounterHistory" Height="75" ItemsSource="{Binding MyCounter.HistoryList}"></ListView>
</StackPanel>
and code changes like this:
和代码更改如下:
public partial class MainWindow : Window
{
public MyModel MyModel { get; set; }
public MainWindow()
{
InitializeComponent();
//MyModel = new MyModel { MyCounter = new Counter() };
//this.DataContext = MyModel;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
var myModel = this.Resources["myModal"] as MyModel;
if (myModel != null)
{
myModel.MyCounter.incrementCounter();
}
}
}
By the way you should initialize _myCounterin MyModel constructor.
顺便说一句,您应该_myCounter在 MyModel 构造函数中进行初始化。
回答by Kylo Ren
I don't think that your conclusions are entirely right and you have actually ignored the real problem here.
我不认为你的结论是完全正确的,你实际上忽略了这里的真正问题。
just create your property as
只需将您的财产创建为
private MyModel myModel;
public MyModel MyModel
{
get { return myModel;}
set { myModel = value;
NotifyPropertyChanged("MyModel");
}
}
the problem was the MyModelproperty was initialized after the control has been initialized but how would the binding engine know that it has to refresh the view, for it this property is still null as you haven't tell the engine to pull the bound value.
问题是MyModel属性是在控件初始化后初始化的,但是绑定引擎如何知道它必须刷新视图,因为您还没有告诉引擎提取绑定值,因此该属性仍然为空。
or just initialize the value of property before the view that will work too. i. e.
或者只是在也可以工作的视图之前初始化属性的值。IE
public MainWindow()
{
MyModel = new MyModel { MyCounter = new Counter() };
InitializeComponent();
}
So WPF does support the nested/dotted binding.
所以 WPF 确实支持嵌套/点状绑定。

