2011-11-25 105 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