【问题标题】:WPF selecting an Item in a ListBox from the ViewModel using SelectedIndexWPF 使用 SelectedIndex 从 ViewModel 中选择 ListBox 中的项目
【发布时间】:2018-01-15 19:00:53
【问题描述】:

我是 MVVM/WPF 的新手,经过几个小时的研究,没有为我的项目找到任何真正有用/有效的答案,我决定试一试并尝试在这里提问。

我想从我的 Listbox 中选择一个 Item,它使用 List 作为 ItemSource。

相关视图模型:

public class FavoriteStructureVm : INotifyPropertyChanged
{
    #region
    public event PropertyChangedEventHandler PropertyChanged;
    private void OnPropertyChanged(string propertyName)
    {
        if (this.PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
    #endregion

    public ObservableCollection<FavoriteDataVm> Favorites { get; set; }
    public int SelectedIndex { get; set; }
    private FavoriteDataVm _selectedItem;
    public FavoriteDataVm SelectedItem
    {
        set
        {
            _selectedItem = value;
            var item = (FavoriteDataVm)_selectedItem;
            if (item.Type == FavoriteDataType.Add)
            {
                SelectedIndex = 1;
            }
        }
    }
}

ListBox默认包含几个项目,最后一个总是Add类型之一,如果被选中,可以添加一个新项目并默认选择它,或者如果没有新项目则选择之前选择的项目添加。 为了简单,无论是否添加新项目,所选项目都将为 1。

无论我尝试使用OnPropertyChanged 更新的位置和内容,它都不会更新视图中的SelectedIndex,但是,通过将新的FavoriteDataVm 添加/插入到ObservableCollection&lt;FavoriteDataVm&gt; Favorites 中,视图中的SelectedIndex得到更新。 向列表中添加新项目的过程并不总是发生,但我想总是更新SelectedIndex。

相关 XAML:

<ListBox Name="favMenu" ItemsSource="{Binding Favorites}" SelectionMode="Single" 
                         HorizontalAlignment="Center" VerticalAlignment="Top" 
                         BorderThickness="0" Background="Transparent" Height="{Binding ElementName=window, Path=ActualHeight}" 
                         SelectedItem="{Binding SelectedItem, Mode=TwoWay}"
                         SelectedIndex="{Binding SelectedIndex, Mode=TwoWay}"
                         >
                    <ListBox.Resources>
                        <Style TargetType="ListBoxItem">
                            <Setter Property="Template">
                                <Setter.Value>
                                    <ControlTemplate TargetType="ListBoxItem">
                                        <Border Background="Transparent" SnapsToDevicePixels="true">
                                            <ContentPresenter />
                                        </Border>
                                    </ControlTemplate>
                                </Setter.Value>
                            </Setter>
                        </Style>
                    </ListBox.Resources>

                    <!--changing default orientation-->
                    <ListBox.ItemsPanel>
                        <ItemsPanelTemplate>
                            <VirtualizingStackPanel Orientation="Vertical"/>
                        </ItemsPanelTemplate>
                    </ListBox.ItemsPanel>

                    <ListBox.ItemTemplate>
                        <DataTemplate>
                            <Border x:Name="Border"
                                BorderThickness="0" BorderBrush="Black" Background="{x:Null}"
                                Width="60" Height="60" CornerRadius="30" Margin="{Binding Margin}"
                                ToolTip="{Binding Name}">


                                <Image Source="{Binding ImageUri}" Width="60" Height="60" Stretch="UniformToFill">
                                    <Image.Clip>
                                        <EllipseGeometry RadiusX="30" RadiusY="30" Center="30,30"/>
                                    </Image.Clip>
                                </Image>
                            </Border>
                        </DataTemplate>
                    </ListBox.ItemTemplate>

                </ListBox>

我找到了一种解决方法来创建一个虚拟项目并将其删除,因为添加一些东西似乎会更新视图中的SelectedIndex。我不认为它是一种解决方案,因为它有很多缺点。

所以这实际上提出了两个问题:

  • 如何更新列表框的SelectedIndex?

还有一个初学者问题,因为我是 MVVM 新手:

  • 这是 MVVM 的正确实现吗?

【问题讨论】:

    标签: c# wpf xaml mvvm listbox


    【解决方案1】:

    如何更新 ListBox 的 SelectedIndex?

    可以通过获取源集合中SelectedItem的索引来获取选中的索引:

    int selectedIndex = (SelectedItem != null && Favorites != null) ? Favorites.IndexOf(SelectedItem) : -1;
    

    您可以通过设置SelectedItem 属性来选择一个项目:

    SelectedItem = Favorites[1]; //selects the second item
    

    您不应同时绑定ListBox 的SelectedItem 和SelectedIndex 属性。这些必须同步。从 XAML 中删除 SelectedIndex="{Binding SelectedIndex, Mode=TwoWay}"。

    另请注意,如果您打算动态更新源属性,则需要为该属性引发 PropertyChanged 以刷新视图:

    private int _selectedIndex;
    public int SelectedIndex
    {
        get { return _selectedIndex; }
        set { _selectedIndex = value; OnPropertyChanged("SelectedIndex"); }
    }
    
    private FavoriteDataVm _selectedItem;
    public FavoriteDataVm SelectedItem
    {
        set
        {
            _selectedItem = value;
            OnPropertyChanged("SelectedItem");
        }
    }
    

    【讨论】:

      【解决方案2】:

      您没有更新 SelectedIndex 声明应该如下

           private int _selectedIndex ;
           public int SelectedIndex{ 
           get{return _selectedIndex }; 
           set{_selectedIndex=value;OnPropertyChanged("SelectedIndex") }; 
           }
      

      这样当 selectedindex 发生变化时会通知列表

      “对不起,如果有任何拼写错误,我是直接在这里而不是在代码编辑器中编写的,所以您可能会遇到拼写错误”

      【讨论】:

      • 感谢您花时间阅读我的问题!我还没有尝试将事件放在那里,所以它可能会被证明有效(很可能)。等我回家再试一下,有需要的时候更新这个帖子
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-30
      相关资源
      最近更新 更多