![](/img/trans.png)
[英]How to correctly use a button in a listbox itemtemplate / datatemplate?
[英]Property not bound correctly in ListBox DataTemplate
我在獲取列表框以正確綁定到集合時遇到了一些麻煩。
我將提供框架代碼,然后解釋我想要它做什么。
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的建議更改了代碼,但是對文本框所做的更改未反映在屬性本身中。 有任何想法嗎?
在本示例中,我采用的Foo模型類已得到簡化,但是省略的代碼可能是導致問題的根源。 讓我解釋。
Foo還需要實現INotifyPropertyChanged,以便在初始化Bars集合時讓Listbox知道,而這絕對取決於初始化它的時間。
假設您在Foo的構造函數中初始化Bars,將導致Listbox ItemsSource綁定到有效的Bars集合。
public Foo()
{
Bars = new ObservableCollection<string>();
...
}
Buut,如果您這樣做,列表框將不知道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}" />
其次,為ItemsSource
設置Mode="TwoWay"
沒有意義。 ItemsSource =“ {Binding Main.SelectedFoo.Bars
,Mode = TwoWay
}”
最后,您不需要為DataTemplate
設置DataType
。
DataType =“ {x:Type系統:字符串}”
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.