Изменение свойства MVVM в поведении <TreeView> - PullRequest
0 голосов
/ 06 апреля 2020

Я не могу получить изменения в пользовательском интерфейсе (TextBox) при выборе элемента дерева. Когда я выбираю элемент дерева, свойство и текст должны измениться. Но этого не происходит. Свойство меняется, но текст остается прежним. Сначала я попытался вызвать изменение свойства в MainViewModel, но столкнулся с той же проблемой: свойство изменяется, но пользовательский интерфейс остается неизменным.

    public class BindableSelectedItemBehavior : Behavior<TreeView>, INotifyPropertyChanged
    {
        MainViewModel vm = new MainViewModel();

        private string _message;
        public string Message
        {
            get
            {
                return _message;
            }

            set
            {
                _message = value;
                OnPropertyChanged("Message");
            }
        }
        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        public object SelectedItem
        {
            get { return GetValue(SelectedItemProperty); }
            set { SetValue(SelectedItemProperty, value); }
        }

        public static readonly DependencyProperty SelectedItemProperty =
            DependencyProperty.Register(nameof(SelectedItem), typeof(object), typeof(BindableSelectedItemBehavior), new UIPropertyMetadata(null, OnSelectedItemChanged));

        private static void OnSelectedItemChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            var item = e.NewValue as TreeViewItem;
            if (item != null)
            {
                item.SetValue(TreeViewItem.IsSelectedProperty, true);
            }
        }

        protected override void OnAttached()
        {
            base.OnAttached();

            AssociatedObject.SelectedItemChanged += OnTreeViewSelectedItemChanged;
        }

        protected override void OnDetaching()
        {
            base.OnDetaching();

            if (AssociatedObject != null)
            {
                AssociatedObject.SelectedItemChanged -= OnTreeViewSelectedItemChanged;
            }
        }

        private void OnTreeViewSelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
        {
            SelectedItem = e.NewValue;
            string name = GetName((Item)SelectedItem);
            Message = "edgddgdgdg";
        }
        public string GetName(Item item)
        {
            string circ = item.Name;
            return circ;
        }
    }
}
    <UserControl x:Class="WpfApp3.TreeViewTextChange"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:WpfApp3"
             xmlns:vm="clr-namespace:WpfApp3.ViewModel"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <UserControl.DataContext>
        <vm:BindableSelectedItemBehavior/>
    </UserControl.DataContext>
    <Grid>
        <TextBox Grid.Row="1" Grid.Column="2" Text="{Binding Path=Message, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Background="Aqua" Width="200" Height="50"/>
    </Grid>
</UserControl>

Использовал отладчик - свойство изменяется, но не изменяется текстовое поле в UserControl. Моя MainViewModel

    class MainViewModel : BindableBase
    {

        MainModel mainModel = new MainModel();
        private ICollectionView root;
        public MainViewModel()
        {
            OpenSth = new DelegateCommand(DisplayItemTree);
            ShowCheck = new DelegateCommand(ShowCheckedItemsCommand);
            Sth = new DelegateCommand(Changetext);
            TextChengedCommand = new DelegateCommand<object>(textChange);
        }
        public ICommand OpenSth { get; }
        public ICommand ShowCheck { get; }
        public ICommand Sth { get; }
        public ICommand TextChengedCommand { get; }

        private void textChange(object obj)
        {
            var str = obj as string;
        }
        public void DisplayItemTree()
        {
            var itemTree = mainModel.GetItemsTree();
            Root = CollectionViewSource.GetDefaultView(itemTree);
            Root.Filter = new Predicate<object>((item) =>
            {
                var realItem = (Item)item;
                return true;
            });
            Root.Refresh();
        }
        public ICollectionView Root
        {
            get => root;
            set => SetProperty(ref root, value);
        }
        public void ShowCheckedItemsCommand()
        {
            var str = new StringBuilder();
            List<Item> items = mainModel.FindCheckedItem();
            if (items.Count == 0)
            {
                str.Append("No selected items");
            }
            else
            {
                foreach (var item in items)
                {
                    str.Append(item.Name);
                }
            }
            MessageBox.Show(str.ToString());
        }

        private string _name;
        public string TextText
        {
            get { return _name; }
            set
            {
                _name = value;
                RaisePropertyChanged("TextText");
            }
        }

        public void Changetext()
        {
            TextText = "dggg";
        }

    }
}

И код xaml

<Window x:Class="WpfApp3.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:local="clr-namespace:WpfApp3"
        xmlns:beh="clr-namespace:WpfApp3.ViewModel"
        xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
        xmlns:ii="http://schemas.microsoft.com/expression/2010/interactivity"
        xmlns:prism="http://www.codeplex.com/prism"
        mc:Ignorable="d"
        xmlns:vm="clr-namespace:WpfApp3.ViewModel"
        xmlns:bh="clr-namespace:WpfApp3.ViewModel"
        Title="MainWindow" Height="450" Width="800">
    <Window.DataContext>
        <vm:MainViewModel/>
    </Window.DataContext>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="50"/>
            <ColumnDefinition Width="200"/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <DockPanel Grid.Column="1" Grid.Row="0" Grid.RowSpan="2">
            <TextBox x:Name="searchBox" DockPanel.Dock="Top" Height="30" VerticalAlignment="Top" BorderBrush="Black" BorderThickness="1" Text="{Binding SearchText}">
                <ii:Interaction.Triggers>
                    <ii:EventTrigger EventName="TextChenged">
                        <ii:InvokeCommandAction Command="{Binding TextChengedCommand}" CommandParameter="{Binding ElementName=searchBox, Path=Text}"/>
                    </ii:EventTrigger>
                </ii:Interaction.Triggers>
            </TextBox>
            <DockPanel DockPanel.Dock="Bottom">
                <Button Content="Get TreeView" Command="{Binding OpenSth}" Width="100"/>
                <Button Content="Show Check Item" Command="{Binding ShowCheck}" Width="100"/>
            </DockPanel>
            <TreeView BorderBrush="Black" BorderThickness="1" ItemsSource="{Binding Root}">
                <i:Interaction.Behaviors>
                    <beh:BindableSelectedItemBehavior SelectedItem="{Binding SelectedNode, Mode=TwoWay}"/>
                </i:Interaction.Behaviors>
                <TreeView.ItemTemplate>
                    <HierarchicalDataTemplate ItemsSource="{Binding Sub}">
                        <DockPanel>
                            <CheckBox IsChecked="{Binding CheckedItem}" Margin="0 8 0 8" VerticalAlignment="Center" DockPanel.Dock="Left"/>
                            <TextBlock Text="{Binding Name}" VerticalAlignment="Center" DockPanel.Dock="Right"/>
                        </DockPanel>
                    </HierarchicalDataTemplate>
                </TreeView.ItemTemplate>
            </TreeView>
        </DockPanel>
        <DataGrid AutoGenerateColumns="False" Height="210" HorizontalContentAlignment="Left" Name="DataGrid" VerticalAlignment="Top" Grid.Column="2" Grid.Row="0" Margin="0,0,0,0" ItemsSource="{Binding ListOfCircuets}">
            <DataGrid.Columns>
                <DataGridTextColumn Binding="{Binding Length}" MinWidth="50"/>
                <DataGridTextColumn Binding="{Binding dU}" MinWidth="50"/>
                <DataGridTextColumn Binding="{Binding Cable}" MinWidth="50"/>
                <DataGridTextColumn Binding="{Binding I}" MinWidth="50"/>
            </DataGrid.Columns>
        </DataGrid>
        <TextBox Grid.Row="1" Grid.Column="2" Text="{Binding TextText, Mode=TwoWay}" Background="Aqua" Width="200" Height="50"/>
        <Button Content="Show Check Item" Command="{Binding Sth}" Width="100"/>
        <local:TreeViewTextChange Grid.Row="1" Grid.Column="2"></local:TreeViewTextChange>
    </Grid>
</Window>

...