MVVM Listbox DataTemplate SelectedItem

本文关键字:SelectedItem DataTemplate Listbox MVVM | 更新日期: 2023-09-27 18:15:35

我使用一个ListBox与DataTemplate如下所示(xaml简化和变量名称更改)。

<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解决方案。我不想在文件后面添加代码来解决这个问题,就像他们在链接中所做的那样。

是否有一个干净的解决方案可以在XAML中完成。除了非mvvm解决方案,我还没有发现任何人有这个问题。我本以为这是相当普遍的。

最后,我找到了这个用于命令绑定的Command="{Binding DataContext.CommandName} RelativeSource={RelativeSource FindAncestor, ListBox, 1}。我不完全理解它在做什么,但我知道当我直接绑定到CommandName时,命令没有触发。

MVVM Listbox DataTemplate SelectedItem

您正在使用MVVM ....所以非常简单的解决方案是将SelectedItem作为参数传递给Both按钮的命令然后用参数.....

的值设置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>

这将从您单击按钮的位置获得当前ListBox项....

应该这样做......:)

您需要一些代码来处理您想要的视觉行为,但您不必将其放在视图模型或控件代码中。

我会写一个行为(称为像SelectListBoxItemWhenClickedBehavior),当按钮被点击时,它查找ListBoxItem在可视化树(使用VisualTreeHelper)。然后它可以设置ListBoxItem。IsSelected = true.

该行为只做一件已知的事情,它只由控件的视觉样式(XAML)设置,该样式知道按钮位于ListBoxItem中。我认为这可以保持M-V-VM的关注点分离。

如果你需要帮助写一个行为,告诉我。