2010-10-04 67 views
0

我一直有一些麻煩,獲得一個列表框正確綁定到集合。屬性在列表框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#視圖模型:

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的建議更改了代碼,但對文本框所做的更改未反映在屬性本身中。有任何想法嗎?

回答

2

我爲此示例簡化了您的Foo模型類,但省略的代碼可能是您問題的罪魁禍首。讓我解釋。

Foo還需要實現INotifyPropertyChanged以讓Listbox知道何時初始化了Bars集合,而這絕對取決於您何時初始化它。

假設您初始化Foo的構造函數中的Bars將導致Listbox ItemsSource綁定到有效的Bars集合。

public Foo() 
{ 
    Bars = new ObservableCollection<string>(); 
    ... 
} 

Buut,如果你做了這樣的事情,列表框將不知道該酒吧集合已被初始化,並不會更新它的源...

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默認情況下,這樣你就不會需要設置ModePath

<TextBox Text="{Binding UpdateSourceTrigger=PropertyChanged}" /> 

其次,它是沒有意義的設置Mode="TwoWay"ItemsSource。的ItemsSource = 「{結合Main.SelectedFoo.Bars ,模式=雙向 }」

最後,你並不需要設置DataType爲您DataTemplate DataType =「{x:Type System:String}」

+0

太棒了!非常感謝額外的信息。是的,正如你可以清楚地看到的,我仍然在學習WPF和MVVM,並且我衷心感謝評論。我會試試你的建議。 – llaughlin 2010-10-05 12:36:25

+0

需要注意的一件事:我有'TextBox'綁定的方式,因爲模式是'TwoWay'(甚至默認),所以需要路徑,我在我的XAML註釋中註明了這一點。這似乎是將'TextBox'綁定到集合中的當前項目的唯一方法。 – llaughlin 2010-10-05 15:53:26

相關問題