更新列表框的SelectedItem

时间:2018-11-27 22:13:22

标签: c# wpf data-binding

我有一个列表框,其中包含某些项(已绑定),其中某些项是其他项的“子项”,非常类似于VS 2017中的“调试->选项”窗口的样子。我试图做另一件事就是,当选择父项时,我希望列表框选择该父项的第一个孩子。

当我单击一个孩子时,该孩子表现良好,在这种情况下当然不需要进行任何更新。但是,当我单击父级时,尽管右侧操作正确(看到选定的子级),但列表框仍显示所选的父级。

我可以在构造函数中设置SelectedPane,它可以正确更新列表框。

我已将内容简化为(大多数)裸代码以进行复制。

我的XAML:

<Window x:Class="WPF_Scratch.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:diag="clr-namespace:System.Diagnostics;assembly=WindowsBase"
        xmlns:local="clr-namespace:WPF_Scratch"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.Resources>
        <local:MainVM x:Key="main"/>
    </Window.Resources>
    <Window.DataContext>
        <Binding Source="{StaticResource main}"/>
    </Window.DataContext>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>

        <ListBox Grid.Column="0" ItemsSource="{Binding Panes}" 
                 SelectedItem="{Binding SelectePane, Mode=TwoWay, diag:PresentationTraceSources.TraceLevel=High}">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Name}">
                        <TextBlock.Style>
                            <Style>
                                <Setter Property="Control.Margin" Value="0,0,0,0"/>
                                <Style.Triggers>
                                    <DataTrigger Binding="{Binding Indent}" Value="True">
                                        <Setter Property="Control.Margin" Value="10,0,0,0"/>
                                    </DataTrigger>
                                </Style.Triggers>
                            </Style>
                        </TextBlock.Style>
                    </TextBlock>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
        <TextBlock Grid.Column="1" Text="{Binding Path=SelectePane.Name}"/>
    </Grid>
</Window>

以及背后的代码:

using System.Collections.Generic;
using System.ComponentModel;

namespace WPF_Scratch
{
    public class NotifyPropertyChanged : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        protected void _UpdateField<T>(ref T field, T newValue, [System.Runtime.CompilerServices.CallerMemberName] string propertyName = null)
        {
            if (!EqualityComparer<T>.Default.Equals(field, newValue))
            {
                field = newValue;
                _OnPropertyChanged(propertyName);
            }
        }

        protected virtual void _OnPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    public class MainVM: NotifyPropertyChanged
    {
        public class PaneInfo
        {
            public string Name { get; set; }
            public PaneInfo Child { get; set; }
            public bool Indent { get; set; }
        }

        private PaneInfo[] _panes;
        public PaneInfo[] Panes => _panes;

        private PaneInfo _selectedPane;
        public PaneInfo SelectePane
        {
            get => _selectedPane;
            set
            {
                if (value?.Child != null)
                {
                    //SelectePane = value.Child; 
                    _UpdateField(ref _selectedPane, value.Child);
                }
                else
                    _UpdateField(ref _selectedPane, value);
            }
        }

        public MainVM()
        {
            PaneInfo childOne = new PaneInfo { Name = "Child One", Indent = true };
            PaneInfo parentOne = new PaneInfo { Name = "Parent One", Child = childOne };
            PaneInfo childTwo = new PaneInfo { Name = "Child Two", Indent = true };
            PaneInfo parentTwo = new PaneInfo { Name = "Parent Two", Child = childTwo };

            _panes = new PaneInfo[4]
            {
                parentOne, childOne, parentTwo, childTwo
            };
        }

    }
}

谢谢

0 个答案:

没有答案