WPF MVVM绑定问题/问题

时间:2018-04-24 15:15:36

标签: c# wpf mvvm binding

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

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

调用表单视图模型的第一个视图模型:

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; }
}

它的xaml:

<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绑定运行良好。我的ContentControl显示我的第二个UserControl,但是当我选择一个对象时,绑定在我的表单中不起作用。

这是第二个视图模型:

    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(&#34; Role&#34;),但绑定无法正常工作。

我尝试只使用一个视图模型和一个用户控件,绑定效果很好(但正如预期的那样),当我编辑表单时,列表会在我提交之前更新。也许有更好的方法在同一页面上显示列表和编辑表单。

第二次,我正在寻找一种简单的方法来管理多对多的关系,而无需使用特定的视图。 例如:Role有一个List parsonsByRole,Person有一个List RolesByPerson,我想在Person编辑表单中显示Role和Add / Remove按钮的完整列表,以填充RolesByPerson。也许有更好的方法来做到这一点。

谢谢!

1 个答案:

答案 0 :(得分:0)

感谢我的评论,我现在可以更好地了解它是如何运作的。

这是我的解决方案:

第一个视图模型:

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中加载了视图而不是视图模型,我更改了编辑视图和视图模型的构造函数,以确保不使用默认构造函数。

第二视图模型:

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>

我删除了资源和datacontext标记。

其代码背后:

    public partial class ZRoleEditUserControl : UserControl
{
    public ZRoleEditUserControl(ZRoleEditViewModel context)
    {
        InitializeComponent();
        this.DataContext = context;
    }
}

我的主要问题是修复,绑定运行良好。太好了,我想在创建编辑表单时我必须克隆我的对象Role,或者使用UpdateSourceTrigger = Explicit可能是BindingGroup。

感谢您的帮助!