WPF-Treeviewitems属性的更改未反映在UI问题中 [英] WPF - Changes in treeviewitems' properties not reflected in UI problem

查看:87
本文介绍了WPF-Treeviewitems属性的更改未反映在UI问题中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个用HierarchicalDataTemplates构建的树状视图,我希望能够将JSON文件添加到SegmentInfo节点-如果这样做,则添加了数据,但是更改未反映在UI中(仍然注释说没有数据

I have a tree view built with HierarchicalDataTemplates, I want to be able to add JSON files to SegmentInfo nodes - if I do so, the data is added but the change is not reflected in UI (still the comment says "no data" in red).

我已将列表树视图项设置为ObservableCollection,将其移至继承了INotifyPropertyChanged的 ViewModel类中,我似乎对其进行了设置正确设置后,我已将DataContext设置为Window中的ViewModel对象。
在xaml中,我已将绑定和模式设置为TwoWay。仍然没有帮助

I've made the list the tree view items as ObservableCollection, moved it to a "ViewModel" class that inherits INotifyPropertyChanged, I seem to set it up properly, I've set DataContext to the ViewModel object in my Window. In xaml I've set the bindings and mode as TwoWay. Still nothing helped

XAML:

<Window.Resources>
        <local:BoolToStringConverter x:Key="BoolToStringConverter" FalseValue="no data" TrueValue="has data" />
    </Window.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="auto" MinHeight="384.8"/>
            <RowDefinition Height="35.2"/>
        </Grid.RowDefinitions>
        <TreeView Name="trvTypeInfos" Margin="5" Grid.Row="0" ItemsSource="{Binding Path=TypeInfoList, Mode=TwoWay}">
            <TreeView.Resources>
                <Style TargetType="{x:Type TreeViewItem}">
                    <EventSetter Event="ListBoxItem.PreviewMouseUp" 
                            Handler="ListBoxItem_PreviewMouseUp"/>
                    <Setter Property="IsExpanded" Value="True"/>
                </Style>
                <HierarchicalDataTemplate DataType="{x:Type data:TypeInfo}" ItemsSource="{Binding SegmentInfos, Mode=TwoWay}">
                    <StackPanel Orientation="Horizontal">
                        <TextBlock Text="{Binding Name}" />
                        <TextBlock Text=" [" Foreground="Blue" />
                        <TextBlock Text="{Binding SegmentInfos.Count}" Foreground="Blue"/>
                        <TextBlock Text="]" Foreground="Blue" />
                    </StackPanel>
                </HierarchicalDataTemplate>
                <DataTemplate DataType="{x:Type data:SegmentInfo}">
                    <StackPanel Orientation="Horizontal">
                        <TextBlock Text="{Binding Name}" />
                        <TextBlock Text=" ("/>
                        <TextBlock Text="{Binding Path=HasData, Mode=TwoWay, Converter={StaticResource BoolToStringConverter}}">
                            <TextBlock.Style>
                                <Style TargetType="TextBlock">
                                    <Style.Triggers>
                                        <Trigger Property="Text" Value="no data">
                                            <Setter Property="Foreground" Value="Red"/>
                                        </Trigger>
                                        <Trigger Property="Text" Value="has data">
                                            <Setter Property="Foreground" Value="Green"/>
                                        </Trigger>
                                    </Style.Triggers>
                                </Style>
                            </TextBlock.Style>
                        </TextBlock>
                        <TextBlock Text=")"/>
                    </StackPanel>
                </DataTemplate>
            </TreeView.Resources>
        </TreeView>
        <StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Right">
            <Button  Width="80" Height="20" Content="OK" Margin="5,0, 5, 5" IsDefault="True" Click="OK_Click"/>
            <Button  Width="80" Height="20" Content="Cancel" Margin="5,0, 5, 5" Click="Cancel_Click" />
        </StackPanel>

    </Grid>

窗口类:

public SegmentDataUpdaterDialog(SegmentDataUpdater segmentDataUpdater, List<TypeInfo> typeInfoList)
{
    ViewModel = new ViewModel(typeInfoList);
    DataContext = ViewModel;
    SegmentDataUpdater = segmentDataUpdater;
    InitializeComponent();
}

private void ListBoxItem_PreviewMouseUp(object sender, MouseButtonEventArgs e)
{
    TreeViewItem item = sender as TreeViewItem;
    SegmentInfo segInfo = item.Header as SegmentInfo;
    if (segInfo != null)
    {
        MessageBox.Show(segInfo.JsonContents);
        var filePath = AskForFile();
        bool success = SegmentDataUpdater.TryStoreJson(segInfo, filePath, out string json);
        if (success)
        {
            segInfo.JsonContents = json;
            segInfo.HasData = true;
        }
    }
}

ViewModel类:

ViewModel class:

public class ViewModel : INotifyPropertyChanged
{
    private ObservableCollection<TypeInfo> _typeInfoList;
    public ObservableCollection<TypeInfo> TypeInfoList
    {
        get { return _typeInfoList; }
        set
        {
            if (_typeInfoList==null || !value.All(_typeInfoList.Contains))
            {
                _typeInfoList = value;
                OnPropertyChanged(nameof(TypeInfoList));
            }
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public ViewModel(List<TypeInfo> typeInfos)
    {
        TypeInfoList = new ObservableCollection<TypeInfo>(typeInfos);
    }

    private void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

TypeInfo类:

TypeInfo class:

public class TypeInfo
{
    public string Name { get; set; }
    public ObservableCollection<SegmentInfo> SegmentInfos { get; set; }
    public int ElementId { get; set; }

    public TypeInfo()
    {
        SegmentInfos = new ObservableCollection<SegmentInfo>();
    }
}

SegmentInfo类:

SegmentInfo class:

public class SegmentInfo
{
    public string Name { get; set; }
    public bool HasData { get; set; }
    public string JsonContents { get; set; }
    public int ElementId { get; set; }
}

转换器类别:

public class BoolToValueConverter<T> : IValueConverter
{
    public T FalseValue { get; set; }
    public T TrueValue { get; set; }

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (value == null)
            return FalseValue;
        else
            return (bool)value ? TrueValue : FalseValue;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return value != null ? value.Equals(TrueValue) : false;
    }
}

public class BoolToStringConverter : BoolToValueConverter<String> { }

我希望在将json文件成功添加到SegmentInfo之后,UI会使用有数据评论。
现在,我可以检查数据是否确实添加到SegmentInfo中,但UI不能反映出来。

I expect that after successful adding json file to the SegmentInfo the UI will update the node with "has data" comment. Now I can check that the data is really added to the SegmentInfo but UI doesn't reflect that.

推荐答案

您的 HasData 属性不会更新UI,因为您没有更新它的机制(INotifyPropertyChanged)。 SegmentInfo 需要实现INotifyPropertyChanged。

Your HasData property does not update the UI, as you have no mechanism to update it (INotifyPropertyChanged). SegmentInfo needs to implement INotifyPropertyChanged.

如果您打算将属性绑定到UI,则需要单独发送一个PropertyChanged Notification。因此,在您的 SegmentInfo 类中; 名称 HasData JsonContent 应该分别引发<他们的设置器中的code> OnPropertyChanged 事件。

If you plan to have a property Bind to the UI, it needs to have an PropertyChanged Notification go out for it individually. So on your SegmentInfo class; Name, HasData, and JsonContent should each raise an OnPropertyChanged event in their setter.

一个好方法; XAML中直接绑定的任何内容( Text = {Binding Name} )在更改时都将引发一个事件。如果您绑定任何属性,例如:( Text = {Binding MyThing.Name} ),则当 MyThing.Name 时将不会得到更新。 code>更改。您需要分解属性并直接在其上进行通知。

A good way to think of it; anything that is directly bound in XAML (Text="{Binding Name}") should raise an event when changed. If you bind any properties like: (Text="{Binding MyThing.Name}") you will not get an update when MyThing.Name changes. You need to break out the property and Notify on it directly.

这篇关于WPF-Treeviewitems属性的更改未反映在UI问题中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆