gpt4 book ai didi

c# - WPF MVVM 绑定(bind)问题/疑问

转载 作者:行者123 更新时间:2023-12-03 10:42:37 27 4
gpt4 key购买 nike

我正在用 MVVM 做我的第一个 C# WPF 项目,我有几个问题。

第一,我想从我的模型中列出一些对象,当我点击其中一个时,屏幕上会显示一个表单(或默认情况下创建的表单)。在我的表单中,绑定(bind)不起作用,我找不到原因。

第一个调用表单 View 模型的 View 模型:

public class ZRoleViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;

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

public ZRoleViewModel()
{
IRepository<Role> mRole = new Repository<Role>();
_roles = new ObservableCollection<Role>(mRole.GetAll());

SelectedRole = new Role();
SelectedIndex = -1;

_editRole = new ZRoleEditViewModel();
}

private ObservableCollection<Role> _roles;
private Role _selectedRole;
private int _selectedIndex;
private ZRoleEditViewModel _editRole;

public ObservableCollection<Role> Roles
{
get => _roles;
set
{
_roles = value;
RaisePropertyChanged("Roles");
}
}

public Role SelectedRole
{
get => _selectedRole;
set
{
_selectedRole = value;
RaisePropertyChanged("SelectedRole");
if (_selectedRole != null && _editRole != null)
{
_editRole.Role = _selectedRole;
}
}
}

public int SelectedIndex
{
get => _selectedIndex;
set
{
_selectedIndex = value;
RaisePropertyChanged("SelectedIndex");
}
}

public ZRoleEditViewModel EditRole { get => _editRole; set => _editRole = value; }
}

它的xml:
<UserControl x:Class="WpfPlanAction.View.ZRoleUserControl"
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:WpfPlanAction.View"
xmlns:viewModel="clr-namespace:WpfPlanAction.ViewModel"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<UserControl.DataContext>
<viewModel:ZRoleViewModel/>
</UserControl.DataContext>
<UserControl.Resources>
<DataTemplate DataType="{x:Type viewModel:ZRoleEditViewModel}">
<local:ZRoleEditUserControl/>
</DataTemplate>
</UserControl.Resources>
<Grid>
<DockPanel Margin="10">
<StackPanel DockPanel.Dock="Left">
<TextBlock Text="Rôles" FontWeight="Bold"/>
<DataGrid ItemsSource="{Binding Roles}"
SelectedItem="{Binding SelectedRole}"
SelectedIndex="{Binding SelectedIndex}"
IsReadOnly="True"
SelectionMode="Single"
AutoGenerateColumns="False"
RowHeaderWidth="0">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Libelle}" Header="Libellé"></DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
</StackPanel>
<ContentControl Content="{Binding EditRole}"></ContentControl>
</DockPanel>
</Grid>

在这里,我的 DataGrid 的绑定(bind)运行良好。我的 ContentControl 显示我的第二个 UserControl,但是当我选择一个对象时,绑定(bind)在我的表单中不起作用。

这里是第二个 View 模型:
    public class ZRoleEditViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;

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

public ZRoleEditViewModel()
{
_role = new Role();
}

private Role _role;

public Role Role
{
get => _role;
set
{
_role = value;
RaisePropertyChanged("Role");
}
}
}

和 xaml:
<UserControl
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:WpfPlanAction.View"
xmlns:viewModel="clr-namespace:WpfPlanAction.ViewModel"
xmlns:Model="clr-namespace:WpfPlanAction.Model" x:Class="WpfPlanAction.View.ZRoleEditUserControl"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300" Loaded="UserControl_Loaded">
<UserControl.Resources>
<CollectionViewSource x:Key="roleViewSource" Source="{Binding Role}" d:DesignSource="{d:DesignInstance {x:Type Model:Role}, CreateList=True}"/>
</UserControl.Resources>
<UserControl.DataContext>
<viewModel:ZRoleEditViewModel/>
</UserControl.DataContext>
<Grid>
<Grid x:Name="grid1" VerticalAlignment="Top" Margin="10,10,0,0" HorizontalAlignment="Left" DataContext="{StaticResource roleViewSource}" Width="280">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Label VerticalAlignment="Center" Grid.Row="0" Margin="3" HorizontalAlignment="Left" Grid.Column="0" Content="Abrege:"/>
<TextBox x:Name="abregeTextBox" Width="209" VerticalAlignment="Center" Text="{Binding Abrege, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true}" Grid.Row="0" Margin="3,4,-85,4" Height="24" HorizontalAlignment="Left" Grid.Column="1"/>
<Label VerticalAlignment="Center" Grid.Row="1" Margin="3" HorizontalAlignment="Left" Grid.Column="0" Content="Libelle:"/>
<TextBox x:Name="libelleTextBox" Width="209" VerticalAlignment="Center" Text="{Binding Libelle, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true}" Grid.Row="1" Margin="3,4,-84,4" Height="24" HorizontalAlignment="Left" Grid.Column="1"/>
</Grid>
</Grid>

调用了 RaisePropertyChanged("Role") 但绑定(bind)不起作用。

我尝试只使用一个 View 模型和一个用户控件来完成它,绑定(bind)工作得很好,太好了(但正如预期的那样),当我编辑表单时,列表在我提交之前更新。也许有更好的方法在同一页面上显示列表和编辑表单。

第二次,我正在寻找一种简单的方法来管理多对多关系,而无需使用特定 View 。
例如:角色有一个列表 parsonsByRole 和人有一个列表 RolesByPerson,我想在人编辑表单中显示角色和添加/删除按钮的完整列表来填充 RolesByPerson。也许有更好的方法来做到这一点。

谢谢!

最佳答案

感谢评论,我现在对它的工作原理有了更好的了解。

这是我的解决方案:

第一个 View 模型:

public class ZRoleViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;

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

public ZRoleViewModel()
{
IRepository<Role> mRole = new Repository<Role>();
_roles = new ObservableCollection<Role>(mRole.GetAll());

SelectedIndex = -1;
SelectedRole = new Role();

_editRole = new ZRoleEditViewModel(SelectedRole);
_editUC = new ZRoleEditUserControl(_editRole);
}

private ObservableCollection<Role> _roles;
private Role _selectedRole;
private int _selectedIndex;
private ZRoleEditViewModel _editRole;
private ZRoleEditUserControl _editUC;

public ObservableCollection<Role> Roles
{
get => _roles;
set
{
_roles = value;
RaisePropertyChanged("Roles");
}
}

public Role SelectedRole
{
get => _selectedRole;
set
{
_selectedRole = value;
RaisePropertyChanged("SelectedRole");
if (_selectedRole != null && _editRole != null)
{
_editRole.Role = _selectedRole;
}
}
}

public int SelectedIndex
{
get => _selectedIndex;
set
{
_selectedIndex = value;
RaisePropertyChanged("SelectedIndex");
}
}

public ZRoleEditUserControl EditUC { get => _editUC; }
}

和观点:
<UserControl x:Class="WpfPlanAction.View.ZRoleUserControl"
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:WpfPlanAction.View"
xmlns:viewModel="clr-namespace:WpfPlanAction.ViewModel"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<UserControl.DataContext>
<viewModel:ZRoleViewModel/>
</UserControl.DataContext>
<Grid>
<DockPanel Margin="10">
<StackPanel DockPanel.Dock="Left">
<TextBlock Text="Rôles" FontWeight="Bold"/>
<DataGrid ItemsSource="{Binding Roles}"
SelectedItem="{Binding SelectedRole}"
SelectedIndex="{Binding SelectedIndex}"
IsReadOnly="True"
SelectionMode="Single"
AutoGenerateColumns="False"
RowHeaderWidth="0">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Libelle}" Header="Libellé"></DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
</StackPanel>
<ContentControl Content="{Binding EditUC, Mode=OneTime}" />
</DockPanel>
</Grid>

我在 ContentControl 中加载 View 而不是 View 模型,并更改了我的编辑 View 和 View 模型的构造函数,以确保不使用默认构造函数。

第二个 View 模型:
public class ZRoleEditViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;

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

public ZRoleEditViewModel(Role currentRole)
{
_role = currentRole;
}

private Role _role;

public Role Role
{
get => _role;
set
{
_role = value;
RaisePropertyChanged("Role");
}
}
}

风景:
<UserControl
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:WpfPlanAction.View"
xmlns:viewModel="clr-namespace:WpfPlanAction.ViewModel"
xmlns:Model="clr-namespace:WpfPlanAction.Model" x:Class="WpfPlanAction.View.ZRoleEditUserControl"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300" Loaded="UserControl_Loaded">
<Grid>
<Grid x:Name="grid1" VerticalAlignment="Top" Margin="10,10,0,0" HorizontalAlignment="Left" Width="280">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Label VerticalAlignment="Center" Grid.Row="0" Margin="3" HorizontalAlignment="Left" Grid.Column="0" Content="Abrege:"/>
<TextBox x:Name="abregeTextBox" Width="209" VerticalAlignment="Center" Text="{Binding Role.Abrege, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true}" Grid.Row="0" Margin="3,4,-85,4" Height="24" HorizontalAlignment="Left" Grid.Column="1"/>
<Label VerticalAlignment="Center" Grid.Row="1" Margin="3" HorizontalAlignment="Left" Grid.Column="0" Content="Libelle:"/>
<TextBox x:Name="libelleTextBox" Width="209" VerticalAlignment="Center" Text="{Binding Role.Libelle, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true}" Grid.Row="1" Margin="3,4,-84,4" Height="24" HorizontalAlignment="Left" Grid.Column="1"/>
</Grid>
</Grid>

我删除了资源和数据上下文标签。

其背后的代码:
    public partial class ZRoleEditUserControl : UserControl
{
public ZRoleEditUserControl(ZRoleEditViewModel context)
{
InitializeComponent();
this.DataContext = context;
}
}

我的主要问题是修复,绑定(bind)运行良好。太好了,我想当我创建编辑表单或将 UpdateSourceTrigger=Explicit 与可能的 BindingGroup 一起使用时,我将不得不克隆我的对象角色。

谢谢你的帮助!

关于c# - WPF MVVM 绑定(bind)问题/疑问,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50005228/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com