/ / Powiązanie SelectedItem w DataGrid nie działa - wpf, mvvm, datagrid

Wiązanie SelectedItem na DataGrid nie działa - wpf, mvvm, datagrid

Ten problem dręczy mnie od kilku dni. Okno to podstawowy wpis adresowy, który polega na wysyłaniu zapytań do bazy danych i wyświetlaniu wyników.

Użytkownik najpierw wprowadza ulicę (Bound to Query.Street), następnie miasto (Bound to Query.City), a następnie z listy wyników (DataGrid powiązany z QueryResults) wybiera odpowiednią ulicę.

Zapytanie do bazy danych odbywa się w obiekcie PropertyChanged of Query w ViewModel i działa dobrze. Wiążę ObservableCollection<Location> QueryResults do DataGrid ItemsSource, a gdy w QueryResults pozostał tylko jeden element, przypisuję go do Location SelectedAddress lubię to (this będąc ViewModelem):

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

Subskrybuję to zdarzenie w konstruktorze ViewModel.

QueryResults w ViewModel:

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

To jest SelectedAddress własność:

internal Location _selectedAddress = new Location();

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

Następnie wiążę this.SelectedAddress do SelectedItem DataGrid, aby mógł go wizualnie zaznaczyć. Kod 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 jest tylko po to ScrollIntoView wybrany wiersz.

SelectedAddress jest również powiązany z panelem, który wyświetla wybrany adres i opis (jest to samodzielna właściwość w ViewModel, która jest kopiowana do SelectedAddress gdy się zmienia), które użytkownik może wprowadzić, aby użytkownik mógł dwukrotnie sprawdzić, czy wybrał prawidłowy adres:

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

Problem jest tak, że istnieje tylko jeden element w DataGrid (lub po równo w QueryResults), Chcę go wybrać automatycznie (sprawdzam, kiedy QueryResults zmienia się i jeśli zawiera tylko jedną pozycję, przypisz ją do SelectedAddress), tak aby DataGrid zaktualizował wybrany element. Tak się nie dzieje. SelectedAddress właściwość w zmianach ViewModel, plik OnPropertyChanged("SelectedAddress"); jest wywoływana, jednak DataGrid nie wybiera jedynego pozostałego wiersza, ani DockPanel nie aktualizuje. Jednak gdy kliknę wiersz w DataGrid, plik SelectedAddress jest aktualizowany, a DockPanel aktualizuje się natychmiast.

Każda pomoc będzie bardzo ceniona!

Z góry dziękuję!

Edytować: Resetowanie okien DataContext gdy SelectedAddress zmiany działają, ale jest to obejście, którego raczej bym nie używał.

Odpowiedzi:

0 dla odpowiedzi № 1

Rozgryzłem to.

Mimo że prawidłowo podbijałem PropertyChanged nie wskazałem, że mój ViewModel implementuje interfejs INotifyPropertyChanged, dlatego zmiana nie odbiła się na interfejsie użytkownika.