2011-11-25 174 views
2

我使用的列表框與DataTemplate如下所示(xaml簡化和變量名稱已更改)。MVVM Listbox DataTemplate SelectedItem

<ListBox ItemsSource="{Binding Path=ObservCollectionItems}" 
     SelectedItem="{Binding Path=SelectedItemVar, Mode=TwoWay}"> 
     <ListBox.ItemTemplate> 
      <DataTemplate> 
       <StackPanel> 
        <TextBlock Text="{Binding SomeVar}" /> 
        <Border> 
         <StackPanel> 
          <Button Content="String1" 
            Command="{Binding DataContext.Command1} 
            RelativeSource={RelativeSource FindAncestor, ListBox, 1}}" /> 
          <Button Content="String2" 
            Command="{Binding DataContext.Command2} 
            RelativeSource={RelativeSource FindAncestor, ListBox, 1}}" /> 
         </StackPanel> 
        </Border> 
       </StackPanel> 
      </DataTemplate> 
     <ListBox.ItemTemplate> 
</ListBox> 

我需要SelectedItemVar(依賴項屬性)來更新當我點擊其中一個按鈕。 SelectedItemVar然後用於各個按鈕的命令。當我單擊TextBlockBorder時SelectedItemVar會更新,但當單擊其中一個按鈕時不會更新。我發現這個問題的非MVVM解決方案here。我不想在文件後面添加代碼來解決這個問題,就像他們在鏈接中所做的那樣。

是否有可以在XAML中完成的乾淨解決方案?除了非MVVM解決方案之外,我還沒有發現任何人有這個問題。我原以爲這很常見。

最後,我發現這個命令綁定的這個Command="{Binding DataContext.CommandName} RelativeSource={RelativeSource FindAncestor, ListBox, 1}。我不完全明白它在做什麼,但我知道當我直接綁定到CommandName時,命令沒有被觸發。

+0

一定要把你的SelectedItem綁定放在你的ItemsSource綁定之前。否則,當ItemsSource解除綁定時,SelectedItem將得到null的setter調用。 –

+0

我將確保綁定以該順序進行設置。感謝指針。 – StinkerPeter

回答

3

您正在使用MVVM ....所以很簡單的解決辦法是薪火的SelectedItem作爲參數傳遞給這兩個按鈕的命令,然後設置與參數的值的SelectedItem .....

代碼

public class YourViewmodel 
{ 
    //Other Variables 


    public YourViewModelCtor() 
    { 
     Command1= new RelayCommand(Command1Func); 
    } 

    Public SelectedVar 
    { 
      get {return value;} 
      Set { selectedVar=value; 
         OnPropertyChanged("SelectedVar"); 
       } 
    } 

    //Other Properties 


    void Command1Func(object obj) 
    { 
       SelectedVar= obj as <Your Desired Type>; 

       //Do your thing with SelectedVar ... Do the same for Command2 
    } 
} 

變化在XAML

<StackPanel> 
    <Button Command="{Binding DataContext.Command1}" CommandParameter="{Binding}" 
      Content="String1" /> 
    <Button Command="{Binding DataContext.Command2}" CommandParameter="{Binding}" 
      Content="String2" /> 
</StackPanel> 

這將讓你在那裏你單擊該按鈕當前列表框項目ferom需要....

這個應該可以...... :)

+0

此解決方案效果極佳。這是我希望的簡單XAML解決方案。你能讓我知道'CommandParameter' Binding做了什麼嗎?再次感謝! – StinkerPeter

+0

@StinkerPeter CommandParameter向參數function(「obj」)發送一個參數(在本例中爲當前行單擊),以便您可以將一些值從XAML發送到ViewModel並在那裏處理。 – Ankesh

2

您需要一些代碼來處理您想要的視覺行爲,但是您不必將其放入視圖模型或控制代碼隱藏模型中。

我會寫一個行爲(稱爲類似於SelectListBoxItemWhenClickedBehavior的東西),當按鈕被點擊時,它在可視樹中查找ListBoxItem(使用VisualTreeHelper)。然後它可以設置ListBoxItem.IsSelected = true。

該行爲確實是一個已知的事情,它僅由知道該按鈕位於ListBoxItem內的控件(XAML)的視覺樣式進行設置。我認爲這樣可以讓M-V-VM保持分離狀態。

如果您在撰寫行爲時需要幫助,請告訴我。

+0

如果我需要一些幫助,我會給這個鏡頭並回來。我以前從來沒有寫過,但在求助之前我並不反對!再次感謝。 – StinkerPeter

+0

傑夫,感謝您的幫助。我沒有時間去嘗試你的解決方案。由於易於實施,我拿出了明顯的答案。 – StinkerPeter