如何使用WPF、C#和Net7通过用户控件编辑列表视图的选定项

jgovgodb  于 2023-03-24  发布在  C#
关注(0)|答案(1)|浏览(140)

目前我正在使用c#学习MVVM和WPF。我正在使用MVVM 8、Net 7.0和WPF UI的社区工具包(设计)包和VS 2022。我试图在一个页面上显示一个列表,其中包含从同一个接口继承的不同项目。在同一个页面上,我想用一个用户控件编辑SelectedItem。为此,我目前正在将用户控件直接添加到页面中,使用绑定到SelectedItem。它显示UserControl中的值,但如果我更改某些值,则当我从列表中选择不同的项目时,listview的selectedItem不再更新。此外,我想使用DataTemplate确定的不同usercontrol编辑不同的模型。请看以下图片:
这里是选择的项目1没有编辑

这里是选择的项目2没有编辑

这里是再次选择的项目1,但项目2编辑见第一个文本框,但SelectedItem不再改变

以下是我的两个问题:
1.如何编辑选定的项目并在编辑后更改选定的项目?是否必须实现某种逻辑来处理此问题?
1.如何使用通用控件(如contentcontrol)根据使用数据模板的类型来显示用户控件?如何处理绑定(例如,我必须绑定到content属性的contentcontrol)?在这种情况下,contentcontrol是否是正确的选择?
ListPage.xaml

<ui:UiPage x:Class="EditListItem.Views.Pages.ListPage"
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:local="clr-namespace:EditListItem.Views.Pages"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml"
xmlns:userControls="clr-namespace:EditListItem.Views.UserControls"
Title="ListPage"
d:DataContext="{d:DesignInstance local:ListPage, IsDesignTimeCreatable=False}"
d:DesignHeight="450"
d:DesignWidth="800"
d:Background="{DynamicResource ApplicationBackgroundBrush}"
Foreground="{DynamicResource TextFillColorPrimaryBrush}"
mc:Ignorable="d">

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="9*"></RowDefinition>
        <RowDefinition Height="1*"></RowDefinition>
    </Grid.RowDefinitions>
    <Grid Grid.Row="0">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="6*"></ColumnDefinition>
            <ColumnDefinition Width="4*"></ColumnDefinition>
        </Grid.ColumnDefinitions>
        <ListView ItemsSource="{Binding ViewModel.Actions, Mode=TwoWay}"
                  SelectionMode="Single"
                  SelectedItem="{Binding ViewModel.SelectedAction, Mode=TwoWay}">
        </ListView>
       
        <userControls:TransactionUserControl Grid.Column="1" Transaction="{Binding ViewModel.SelectedAction, Mode=TwoWay}"/>

    </Grid>
    <WrapPanel Grid.Row="1">
        <Button Content="Deposit" Command="{Binding ViewModel.AddDepositCommand}" />
        <Button Content="Withdrawal" Command="{Binding ViewModel.AddWithdrawalCommand}" />
        <Label Content="{Binding ViewModel.SelectedAction, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
    </WrapPanel>
</Grid>
</ui:UiPage>

ListPage.xaml.cs

public partial class ListPage : INavigableView<ViewModels.ListViewModel>
{
        public ViewModels.ListViewModel ViewModel {
            get;
        }

        public ListPage(ViewModels.ListViewModel viewModel)
        {
            ViewModel = viewModel;

            InitializeComponent();
        }
}

ListViewModel.cs

public partial class ListViewModel : ObservableObject, INavigationAware
{
    private bool _isInitialized = false;

    public ObservableCollection<IAction> Actions { get; set; } = new();

    [ObservableProperty] private IAction? _selectedAction;

    public ListViewModel()
    {
        Actions = new() {
            new Deposit() {
                Id = "1",
                Timestamp = "00000000",
                Amount = 0,
                Symbol = "Symbol1"
            },
            new Withdrawal() {
                Id = "2",
                Timestamp = "00000000",
                Amount = 0,
                Symbol = "Symbol2"
            }
        };
    }

    [RelayCommand]
    private async void AddDeposit()
    {
        Actions.Add(new Deposit());
    }

    [RelayCommand]
    private async void AddWithdrawal()
    {
        Actions.Add(new Withdrawal());
    }

}

下面是我想使用的控件:
TransactionUserControl.xaml

<UserControl x:Class="EditListItem.Views.UserControls.TransactionUserControl"
             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:userControls="clr-namespace:EditListItem.Views.UserControls"
             d:Background="{DynamicResource ApplicationBackgroundBrush}"
             d:Foreground="{DynamicResource TextFillColorPrimaryBrush}"
             Foreground="{DynamicResource TextFillColorPrimaryBrush}"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="400" >
    <StackPanel DataContext="{Binding RelativeSource={RelativeSource AncestorType=UserControl}}">
        <TextBox Text="{Binding Transaction.Id, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"/>
        <TextBox Text="{Binding Transaction.Timestamp, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"/>
        <TextBox Text="{Binding Transaction.Amount, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"/>
        <TextBox Text="{Binding Transaction.Symbol, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"/>
    </StackPanel>
</UserControl>

TransactionUserControl.xaml.cs

public partial class TransactionUserControl
{

    private static DependencyProperty _transactionProperty = DependencyProperty.Register(nameof(Transaction), typeof(IAction), typeof(TransactionUserControl), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));

    public IAction Transaction {
       get => (IAction)GetValue(_transactionProperty);
       set => SetValue(_transactionProperty, value);
    }

    public TransactionUserControl()
    {
        //DataContext = this;
        InitializeComponent();
    }

}

最后,接口存款和Withdrawal继承自。模型不是DependencyObjects,仅为纯Model:

public interface IAction
{
    public string Id { get; set; }
    public string Timestamp { get; set; }
    public double Amount { get; set; }
    public string Symbol { get; set; }

}

public record Deposit : IAction
{
    public string Id { get; set; }
    public string Timestamp { get; set; }
    public double Amount { get; set; }
    public string Symbol { get; set; }
}
pkmbmrz7

pkmbmrz71#

Desposit类更改为以下内容,以便在更改其属性时更新UI:

public class Deposit : ObservableObject, IAction
{
    [ObservableProperty]
    private string _id;

    [ObservableProperty]
    private string _timestamp;

    [ObservableProperty]
    private double _amount;

    [ObservableProperty]
    private string _symbol;
}

相关问题