在DataGrid上绑定SelectedItem不起作用

时间:2017-07-07 09:49:06

标签: wpf mvvm datagrid

过去几天这个问题一直困扰着我。该窗口是基本地址条目,通过查询数据库并显示结果。

用户首先进入街道(Bound to Query.Street),然后是city(Bound to Query.City),然后从结果列表(DataGrid绑定到QueryResults)中选择适当的街道。

查询数据库是在ViewModel中的Query对象的PropertyChanged中完成的,它运行良好。我将ObservableCollection<Location> QueryResults绑定到DataGrid ItemsSource,当QueryResults中只剩下一个项目时,我将其分配给Location SelectedAddress,如此(this是ViewModel):

this.PropertyChanged += (sender, e) =>
{
    switch (e.PropertyName)
    {
        case "QueryResults":
            // QueryResult contains only one result
            if (this.QueryResults?.Count == 1)
            {
                // select that result
                this.SelectedAddress = this.QueryResults.First();
            }
            break;
        default:
            break;
    }
};

我在ViewModel构造函数中订阅了这个事件。

ViewModel中的

QueryResults

internal ObservableCollection<Location> _queryResults = new ObservableCollection<Location>();
public ObservableCollection<Location> QueryResults
{
    get { return this._queryResults; }
    set
    {
        this._queryResults.Clear();
        if (value != null)
        {
            foreach (var item in value)
            {
                this._queryResults.Add(item);
            }
        }
        OnPropertyChanged("QueryResults");
    }
}

这是SelectedAddress属性:

internal Location _selectedAddress = new Location();

public Location SelectedAddress
{
    get { return this._selectedAddress; }
    set
    {
        this._selectedAddress = value;
        OnPropertyChanged("SelectedAddress");
    }
}

然后我将this.SelectedAddress绑定到DataGrid的SelectedItem,以便它可以直观地选择它。 DataGrid代码:

<DataGrid Name="dgQueryResults" 
            MaxHeight="212.6" 
            RowHeaderWidth="0"
            AutoGenerateColumns="False"
            CanUserAddRows="False"
            CanUserDeleteRows="False"
            CanUserReorderColumns="False"
            CanUserResizeRows="False"
            IsReadOnly="True"
            VerticalScrollBarVisibility="Hidden"
            ItemsSource="{Binding QueryResults}" 
            SelectionMode="Single"
            SelectionUnit="FullRow"
            SelectedItem="{Binding SelectedAddress, Mode=TwoWay}"
            SelectionChanged="dgQueryResults_SelectionChanged"
            >
    <DataGrid.Resources>
        <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="LightGreen"/>
        <SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="LightGreen"/>
        <Style TargetType="{x:Type DataGridCell}" BasedOn="{StaticResource {x:Type DataGridCell}}">
            <Setter Property="BorderThickness" Value="0"/>
            <Setter Property="Foreground" Value="Black"/>
        </Style>
    </DataGrid.Resources>
    <DataGrid.Columns>
        <DataGridTextColumn Width="*" Binding="{Binding Street}" IsReadOnly="True">
            <DataGridTextColumn.Header>
                <TextBlock Text="Street"/>
            </DataGridTextColumn.Header>
        </DataGridTextColumn>
        <DataGridTextColumn Width="*" Binding="{Binding City}" IsReadOnly="True">
            <DataGridTextColumn.Header>
                <TextBlock Text="City"/>
            </DataGridTextColumn.Header>
        </DataGridTextColumn>
        <DataGridTextColumn Width="*" Binding="{Binding Municipality}" IsReadOnly="True">
            <DataGridTextColumn.Header>
                <TextBlock Text="Municipality"/>
            </DataGridTextColumn.Header>
        </DataGridTextColumn>
    </DataGrid.Columns>
</DataGrid>

dgQueryResults_SelectionChanged只有ScrollIntoView所选行。

SelectedAddress也绑定到一个面板,该面板显示所选地址和描述(这是ViewModel中的一个独立属性,当它发生更改时会被复制到SelectedAddress)用户可以输入,以便用户可以仔细检查他们是否选择了正确的地址:

<DockPanel>
    <TextBlock DockPanel.Dock="Top" Text="Selected address" FontWeight="DemiBold"/>
    <DockPanel DockPanel.Dock="Bottom">
        <TextBlock DockPanel.Dock="Top" Text="Floor, extra description:"/>
        <TextBlock DockPanel.Dock="Bottom" Text="{Binding Description}"/>
    </DockPanel>
    <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" DataContext="{Binding SelectedAddress}">
        <StackPanel>
            <TextBlock Text="Street" HorizontalAlignment="Left"/>
            <TextBlock Text="{Binding Street}" HorizontalAlignment="Left"/>
        </StackPanel>
        <StackPanel>
            <TextBlock Text="House number" HorizontalAlignment="Left"/>
            <TextBlock Text="{Binding HouseNumber}" HorizontalAlignment="Left"/>
        </StackPanel>
        <StackPanel>
            <TextBlock Text="City" HorizontalAlignment="Left"/>
            <TextBlock Text="{Binding City}" HorizontalAlignment="Left"/>
        </StackPanel>
        <StackPanel>
            <TextBlock Text="Municipality" HorizontalAlignment="Left"/>
            <TextBlock Text="{Binding Municipality}" HorizontalAlignment="Left"/>
        </StackPanel>
    </StackPanel>
</DockPanel>

问题是当DataGrid中只剩下一个项目时(或同样位于QueryResults中),我想自动选择它(我在{{1时检查)更改,如果它只包含一个项目,则将其分配给QueryResults),以便DataGrid更新其选定的项目。这不会发生。 ViewModel中的SelectedAddress属性发生更改,调用SelectedAddress,但DataGrid不会选择剩余的唯一行,也不会更新DockPanel。但是,当我单击DataGrid中的一行时,OnPropertyChanged("SelectedAddress");会更新,DockPanel会立即更新。

非常感谢任何帮助!

提前致谢!

修改SelectedAddress更改有效时重置窗口DataContext,但这是我不想使用的解决方法。

1 个答案:

答案 0 :(得分:0)

我明白了。

即使我正在提升PropertyChanged事件,我也没有表明我的ViewModel实现了接口INotifyPropertyChanged,因此这就是为什么更改没有反映在UI上。