我在使列表框正确绑定到集合时遇到了一些麻烦。
我将给出框架代码,然后解释我希望它做什么。
XAML加价:
<ListBox DataContext="{Binding Foos, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
ItemsSource="{Binding}" IsSynchronizedWithCurrentItem="True"
SelectedItem="{Binding Main.SelectedFoo, Mode=TwoWay,
Source={StaticResource Locator},
UpdateSourceTrigger=PropertyChanged}"
SelectedValue="{Binding Main.SelectedFoo, Source={StaticResource Locator}}"/>
<ListBox ItemsSource="{Binding Main.SelectedFoo.Bars}" SelectedItem="{Binding Main.SelectedBar}" >
<ListBox.ItemTemplate>
<DataTemplate>
<Grid HorizontalAlignment="Right">
<!-- The binding requires "{Binding .}" because a path must be explicitly set for Two-Way binding,
even though {Binding .} is supposed to be identical to {Binding} -->
<TextBox Text="{Binding Path=. , UpdateSourceTrigger=PropertyChanged}" />
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
C#ViewModel:
private ObservableCollection<Foo> _barList = new ObservableCollection<Foo>();
private const string BardListPN = "FooList";
public ObservableCollection<Foo> FooList
{
get { return _fooList; }
set
{
if (_fooList == value)
{
return;
}
var oldValue = _fooList;
_fooList = value;
RaisePropertyChanged(FooListPN);
}
}
private Foo _selectedFoo;
private const string SelectedFooPN = "SelectedFoo";
public Foo SelectedFoo
{
get { return _selectedFoo; }
set
{
if (_selectedFoo == value)
{
return;
}
var oldValue = _selectedFoo;
_selectedFoo = value;
// Update bindings, no broadcast
RaisePropertyChanged(SelectedFooPN);
}
}
public const string SelectedBarPN = "SelectedBar";
private string _selectedBar = "";
public string SelectedBar
{
get
{
return _selectedBar;
}
set
{
if (_selectedBar == value)
{
return;
}
var oldValue = _selectedBar;
_selectedBar = value;
// Update bindings, no broadcast
RaisePropertyChanged(SelectedBarPN);
}
}
C#型号:
public class Foo
{
public ICollection<string> Bars
{
get { return _bars; }
set
{
_bars= value;
NotifyPropertyChanged("Bars");
// snipped obvious INotifyPropertyChanged boilerplate code
}
}
}
我的问题是没有设置Bar
集合中字符串的文本框的任何更改。当选定的Foo
更改为其他Foo
并返回时,会显示原始Bars
。
有人能告诉我我做错了什么吗?这似乎应该简单得多。谢谢!
更新:我已根据Tri Q的建议更改了代码,但对文本框所做的更改未反映在属性本身中。有什么想法吗?
答案 0 :(得分:2)
我为此示例简化了我的Foo模型类,但省略的代码可能是您问题的罪魁祸首。让我解释一下。
Foo还需要实现INotifyPropertyChanged,让Listbox知道你何时初始化了Bars集合,这绝对取决于你何时初始化它。
假设您在Foo的构造函数中初始化Bars将导致Listbox ItemsSource绑定到有效的Bars集合。
public Foo()
{
Bars = new ObservableCollection<string>();
...
}
如果你做了类似的事情,那么Listbox将不会知道Bars集合已经初始化并且不会更新它的源代码......
public Foo SelectedFoo
{
get { return _selectedFoo; }
set
{
if (_selectedFoo == value)
{
return;
}
var oldValue = _selectedFoo;
_selectedFoo = value;
// Update bindings, no broadcast
RaisePropertyChanged(SelectedFooPN);
if(_selectedFoo.Bars == null)
{
_selectedFoo.Bars = new ObservableCollection<string>();
// ...
}
}
}
此外,您可能需要在XAML中修改一些内容。
首先,Textbox
的绑定默认为TwoWay
,因此您无需设置Mode
或Path
。
<TextBox Text="{Binding UpdateSourceTrigger=PropertyChanged}" />
其次,为Mode="TwoWay"
设置ItemsSource
是没有意义的。 ItemsSource =“{Binding Main.SelectedFoo.Bars ,Mode = TwoWay }”
最后,您无需为DataType
设置DataTemplate
。 DataType =“{x:Type System:String}”