如何在WPF列表视图(可观察集合)中更新列表项(可观察对象)

wkyowqbh  于 2022-11-18  发布在  其他
关注(0)|答案(1)|浏览(220)

我有一个仪器集合,我想在将它们添加到列表后对每个仪器进行配置
目前,该仪器被定义为继承自ObservableObject的类,并存储在ObservableCollection中,显示为带有仪器详细信息数据模板的Listview。
现在我可以添加/删除仪器,但当我尝试更新仪器详细信息(例如名称、类型)时,仪器类属性未更新。
我正在使用CommunityToolkit.Mvvm,我测试了如果我只是把一个仪器的详细信息放在textbox中作为主窗口中的direct元素,而不是作为listviewitem工作,它会工作。那么这是否意味着我不能把observableObject放在另一个observableObject/ObserverbaleCollection下?

<ListView x:Name="ListView_Instr" 
                  ItemsSource="{Binding InstrumentConfigs, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" 
                  SelectedItem="{Binding SelectInstrumentConfig, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" 
                  Padding="5,5,5,5" Grid.Row="0">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <Grid Width="{Binding Width, ElementName=ListView_Instr}">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="*"/>
                            <ColumnDefinition Width="2*"/>
                            <ColumnDefinition Width="3*"/>
                            <ColumnDefinition Width="3*"/>
                            <ColumnDefinition Width="2*"/>
                        </Grid.ColumnDefinitions>
                        <CheckBox x:Name="CheckBox_InstrChecked" Grid.Column="0"/>
                        <StackPanel Orientation="Horizontal" Grid.Column="1">
                            <Label Content="Type"/>
                            <ComboBox x:Name="ComboBox_InstrType" ItemsSource="{Binding InstrTypes, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"/>
                        </StackPanel>
                        <StackPanel Orientation="Horizontal" Grid.Column="2">
                            <Label Content="Name"/>
                            <TextBox x:Name="TextBox_InstrName" Text="{Binding InstrName, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" />
                        </StackPanel>
                        <StackPanel Orientation="Horizontal" Grid.Column="3">
                            <Label Content="Addr"/>
                            <TextBox x:Name="TextBox_InstrAddr" Text="{Binding InstrAddr, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" />
                        </StackPanel>
                        <StackPanel Orientation="Horizontal" Grid.Column="4">
                            <Label Content="Interface"/>
                            <ComboBox x:Name="ComboBox_InstrInterface" ItemsSource="{Binding InstrInterfaceTypes, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"/>
                        </StackPanel>
                    </Grid>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>

我在使用Observable时遗漏了哪些细节?
谢谢

w1jd8yoj

w1jd8yoj1#

下面的方法应该行得通。
Instrument.cs

using CommunityToolkit.Mvvm.ComponentModel;

namespace wpf_binding
{
    [INotifyPropertyChanged]
    public partial class Instrument
    {
        [ObservableProperty]
        private string name;

        [ObservableProperty]
        private string description;

        partial void OnNameChanged(string value)
        {
            System.Console.WriteLine($"Name changed: {Name}");
        }

        partial void OnDescriptionChanged(string value)
        {
            System.Console.WriteLine($"Description changed: {Description}");
        }
    }
}

ViewModel.cs

using CommunityToolkit.Mvvm.ComponentModel;
using System.Collections.ObjectModel;

namespace wpf_binding
{
    [INotifyPropertyChanged]
    public partial class ViewModel
    {
        [ObservableProperty]
        private ObservableCollection<Instrument> instruments;

        [ObservableProperty]
        private Instrument selectedItem;

        public ViewModel()
        {
            Instruments = new ObservableCollection<Instrument>()
            {
                new Instrument() { Name = "Item 1", Description = "Desc 1" },
                new Instrument() { Name = "Item 2", Description = "Desc 2" }
            };
        }
    }
}

MainWindow.xaml

<Window x:Class="wpf_binding.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:wpf_binding"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <StackPanel Orientation="Vertical">

        <ListView ItemsSource="{Binding Instruments}" SelectedItem="{Binding SelectedItem}">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal">
                        <TextBox Text="{Binding Name, Mode=TwoWay}"/>
                        <TextBox Text="{Binding Description, Mode=TwoWay}"/>
                    </StackPanel>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>

        <StackPanel Orientation="Vertical">
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="Name:"/>
                <TextBlock Text="{Binding SelectedItem.Name}"/>
            </StackPanel>
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="Description:"/>
                <TextBlock Text="{Binding SelectedItem.Description}"/>
            </StackPanel>
        </StackPanel>
    </StackPanel>
</Window>

MainWindow.xaml.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace wpf_binding
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = new ViewModel();
        }
    }
}

相关问题