【问题标题】:MVVM issue with binding a combobox to a datagrid将组合框绑定到数据网格的 MVVM 问题
【发布时间】:2012-12-21 20:03:35
【问题描述】:

我有一个主/详细信息视图。我有一些文本框和一个组合框绑定到数据网格的选定项。我想要的是文本框和组合框,用于在选择一行时填充数据网格中的数据。这部分工作正常。我遇到的问题是当我更改组合框的值时,数据网格字段没有更新。我已经实现了 INotifyPropertyChanged,但似乎我有问题。数据网格包含用户类型的记录,相关的组合框包含角色类型的记录。 User 实体具有到 RoleID 的导航属性。如何确保在更改详细信息中的角色组合框时数据网格会更新?

谢谢,

RG

这里是 XAML...

<UserControl x:Class="Compliance.Views.UserAdministrationView"
         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:Compliance"
         xmlns:views="clr-namespace:Compliance.Views"
         xmlns:helpers="clr-namespace:Compliance.Helpers"
         xmlns:vm="clr-namespace:Compliance.ViewModels"
         xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"
         mc:Ignorable="d" 
         d:DesignHeight="1000" d:DesignWidth="800">
<UserControl.Resources>
    <helpers:ActiveStatusConverter x:Key="ActiveStatusConverter"/>
</UserControl.Resources>
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
    </Grid.RowDefinitions>
    <StackPanel Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Row="0" Margin="15">
        <Label Content="User" Height="25" FontSize="14" HorizontalContentAlignment="Center" />
        <Grid HorizontalAlignment="Center" VerticalAlignment="Top" DataContext="{Binding ElementName=usersDG, Path=SelectedItem, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto" />
                <ColumnDefinition Width="Auto" />
                <ColumnDefinition Width="Auto" />
                <ColumnDefinition Width="Auto" />
                <ColumnDefinition Width="Auto" />
                <ColumnDefinition Width="Auto" />
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" MinHeight="35" />
            </Grid.RowDefinitions>
            <telerik:Label Content="User Name: " Grid.Column="0" Grid.Row="0" HorizontalAlignment="Right" VerticalAlignment="Center" />
            <TextBox Grid.Column="1" Grid.Row="0" MinHeight="23" HorizontalAlignment="Left" VerticalAlignment="Center" MinWidth="180" MaxWidth="180" >
                <TextBox.Text>
                    <Binding Path="UserName" Mode="TwoWay" ValidatesOnDataErrors="True" NotifyOnValidationError="True" UpdateSourceTrigger="PropertyChanged"/>
                </TextBox.Text>                    
            </TextBox> 
            <telerik:Label Content="First Name: " Grid.Column="2" Grid.Row="0" HorizontalAlignment="Right" VerticalAlignment="Center" />
            <TextBox Grid.Column="3" Grid.Row="0" MinHeight="23" HorizontalAlignment="Left" VerticalAlignment="Center" MinWidth="180" MaxWidth="180">
            <TextBox.Text>
                <Binding Path="FirstName" Mode="TwoWay" ValidatesOnDataErrors="True" NotifyOnValidationError="True" UpdateSourceTrigger="PropertyChanged"/>
            </TextBox.Text>
            </TextBox>
            <telerik:Label Content="Last Name: " Grid.Column="4" Grid.Row="0" HorizontalAlignment="Right" VerticalAlignment="Center" />
            <TextBox Grid.Column="5" Grid.Row="0" MinHeight="23" HorizontalAlignment="Left" VerticalAlignment="Center" MinWidth="180" MaxWidth="180">
            <TextBox.Text>
                <Binding Path="LastName" Mode="TwoWay" ValidatesOnDataErrors="True" NotifyOnValidationError="True" UpdateSourceTrigger="PropertyChanged"/>
            </TextBox.Text>
            </TextBox>
            <telerik:Label Content="Email: " Grid.Column="0" Grid.Row="1" HorizontalAlignment="Right" VerticalAlignment="Center" />
            <TextBox Grid.Column="1" Grid.Row="1" MinHeight="23" HorizontalAlignment="Left" VerticalAlignment="Center" MinWidth="180" MaxWidth="180">
                <TextBox.Text>
                    <Binding Path="Email" Mode="TwoWay" ValidatesOnDataErrors="True" NotifyOnValidationError="True" UpdateSourceTrigger="PropertyChanged"/>
                </TextBox.Text>
            </TextBox>
            <telerik:Label Content="Active Status: " Grid.Column="2" Grid.Row="1" HorizontalAlignment="Right" VerticalAlignment="Center" />
            <telerik:RadComboBox x:Name="comBoxActiveStatus" Grid.Column="3" Grid.Row="1" MinHeight="23" MinWidth="180" HorizontalAlignment="Left" VerticalAlignment="Center"
                    SelectedItem="{Binding Path=ActiveStatus, 
                                    Converter={StaticResource ResourceKey=ActiveStatusConverter}, 
                                    Mode=TwoWay, 
                                    ValidatesOnExceptions=True, 
                                    NotifyOnValidationError=True,
                                    UpdateSourceTrigger=PropertyChanged}"
                    EmptyText="Please Set Active Status">
            </telerik:RadComboBox>
            <telerik:Label Content="Role: " Grid.Column="4" Grid.Row="1" HorizontalAlignment="Right" VerticalAlignment="Center" />
            <telerik:RadComboBox x:Name="cmbRoles" 
                        Grid.Column="5" 
                        Grid.ColumnSpan="3"
                        Grid.Row="1" 
                        MinHeight="23" 
                        HorizontalAlignment="Left" 
                        Margin="5" 
                        VerticalAlignment="Center" 
                        MinWidth="180" 
                        ItemsSource="{Binding}" 
                        DisplayMemberPath="RoleName" 
                        SelectedValue="{Binding RoleID, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                        SelectedValuePath="RoleID"
                        EmptyText="Please Choose A Role">
            <telerik:RadComboBox.ItemsPanel>
                <ItemsPanelTemplate>
                    <VirtualizingStackPanel />
                </ItemsPanelTemplate>
            </telerik:RadComboBox.ItemsPanel>
            </telerik:RadComboBox>
            <Button Grid.Column="0" Grid.Row="2" Grid.ColumnSpan="3" Content="Save User" Width="100"  />
            <Button Grid.Column="4" Grid.Row="2" Grid.ColumnSpan="3" Content="Add User"  Width="100"  />
        </Grid>
    </StackPanel>
    <Border CornerRadius="10" BorderThickness="5" Grid.Row="1" VerticalAlignment="Top" HorizontalAlignment="Center">
        <Grid HorizontalAlignment="Center" VerticalAlignment="Center">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
            </Grid.RowDefinitions>
            <Label Content="Users" Grid.Row="0" Height="25" FontSize="14" HorizontalContentAlignment="Center" />
            <telerik:RadGridView x:Name="usersDG" ItemsSource="{Binding Users}" AutoGenerateColumns="False" ShowGroupPanel="False" IsReadOnly="True">
                <telerik:RadGridView.Columns>
                    <telerik:GridViewDataColumn DataMemberBinding="{Binding UserName}" Header="User Name" />
                    <telerik:GridViewDataColumn DataMemberBinding="{Binding FirstName}" Header="First Name" />
                    <telerik:GridViewDataColumn DataMemberBinding="{Binding LastName}" Header="Last Name" />
                    <telerik:GridViewDataColumn DataMemberBinding="{Binding Email}" Header="Email" />
                    <telerik:GridViewDataColumn DataMemberBinding="{Binding Role.RoleName, Mode=TwoWay}" Header="Role Name" />
                    <telerik:GridViewDataColumn DataMemberBinding="{Binding ActiveStatus, Converter={StaticResource ActiveStatusConverter}}" Header="Active Status" />
                </telerik:RadGridView.Columns>
            </telerik:RadGridView>
        </Grid>
    </Border>
</Grid>

【问题讨论】:

  • 某些属性或控件不默认为Mode=TwoWay。我会先检查是否能解决您的问题。
  • 我确实设置了双向模式。
  • 如果您发布一些源代码会有所帮助。

标签: wpf mvvm binding datagrid combobox


【解决方案1】:

您的 ComboBox 绑定看起来很奇怪

您有ItemsSource="{Binding }",这表明ComboBox 的DataContext 是一个角色对象的集合,但是您也有SelectedValue="{Binding RoleID},这表明DataContext 包含一个名为RoleId 的属性

此外,您的GridView 绑定到Role.RoleName,所以我希望您希望将您的ComboBox.SelectedValue 绑定到Role.RoleIdComboBox.SelectedItem 到属性Role,如果它们引用相同的话Role 内存中的对象。

所以我希望你的 ComboBox 绑定看起来像

<ComboBox ItemsSource="{Binding Source={x:Static local:StaticLists.RoleList}}"
          SelectedValue="{Binding Role.RoleID}" ... />

或类似的东西:

<ComboBox ItemsSource="{Binding 
              RelativeSource={RelativeSource AncestorType={x:Type views:UserAdministrationView}},
              Path=DataContext.AvailableRoles}"
          SelectedItem="{Binding Role}" ... />

我建议查看您的 ComboBox.DataContext 是什么(我使用 Snoop 来调试此类事情),并仔细检查您的绑定是否正确

【讨论】:

  • 嗨,瑞秋。 ComboBox 的 ItemsSource 绑定到从数据库中提取的角色列表。数据网格绑定到具有 RoleID 导航属性的用户 ObservableCollection。我已将文本框和组合框绑定到数据网格选定项。当我单击数据网格中的一行时,文本框和组合框会相应更改。更改文本框中的数据会更新数据网格中的行,但更改组合框不会更新数据网格中的角色。这就是我遇到问题的地方。
  • @user1599271 如果没有看到您的确切代码,很难判断问题出在哪里,但是有一些事情可以尝试。首先,如果您的 ComboBox.SelectedValue 绑定到 User.RoleId,则确保更改 User.RoleId 会触发 PropertyChange 通知 User.Role,因为这是您的 DataGrid 绑定的。其次,您可以尝试将ComboBox.SelectedItem 绑定到User.Role,但是要确保它们都指向同一个对象引用,或者覆盖Role.Equals() 方法以在ID匹配时将对象视为相同
  • @user1599271 最后,这可能是 Telerik 的 GridView 控件的一个怪癖(我过去发现他们的 WPF 控件有一些奇怪的怪癖),其中属性没有更新在Role 上带有PropertyChange 通知,它需要Role.RoleName 的PropertyChange 通知。因此,您可以尝试在 User.RoleId 更改时手动触发 User.Role.RoleName 的属性更改通知。
猜你喜欢
  • 1970-01-01
  • 2012-06-05
  • 1970-01-01
  • 2017-12-08
  • 2014-03-01
  • 2021-02-16
  • 1970-01-01
  • 2023-03-08
  • 1970-01-01
相关资源
最近更新 更多