简体   繁体   中英

WPF change notification of user control inside item template not working

I'm trying to bind each view model in an ObservableCollection<FilterControlViewmodel> as DataContext to a user control FilterControl in an ItemsControl .

The binding itself works fine. "InitialFilterName" is displayed correctly from FilterControlViewmodel.FilterName but any updates on the property are not notified to the UI.

Also adding elements to ObservableCollection<FilterControlViewmodel> is working find and adding additional user controls. But again the values inside the FilterControlViewmodel are not updated to the UI.

Any hint on where the notification is missing is appreciated. Thanks.

MainWindow.xaml

<Window.DataContext>
   <local:MainWindowViewmodel/>
</Window.DataContext>

<Grid>
   <ItemsControl ItemsSource="{Binding FilterViewmodel.FilterControls}">
      <ItemsControl.ItemTemplate>
          <DataTemplate>
             <filter:FilterControl DataContext="{Binding}"></filter:FilterControl>
          </DataTemplate>
       </ItemsControl.ItemTemplate>
  </ItemsControl>
</Grid>

FilterControl.xaml

<UserControl.DataContext>
   <local:FilterControlViewmodel/>
</UserControl.DataContext>

<Grid>
   <Label Grid.Column="0" Grid.Row="0" Content="{Binding FilterName}"></Label>
   <ComboBox Grid.Column="0" Grid.Row="1" ItemsSource="{Binding FilterValues}" SelectedItem="{Binding FilterValueSelected}"></ComboBox>
   <Button Grid.Column="1" Grid.Row="1" Content="X" Command="{Binding ResetFilterCommand}"></Button>
</Grid>

MainWindowViewmodel.cs

public class MainWindowViewmodel : INotifyPropertyChanged
{
   public FilterViewmodel FilterViewmodel
        {
            get => _filterViewmodel;
            set
            {
                if (Equals(value, _filterViewmodel)) return;
                _filterViewmodel = value;
                OnPropertyChanged();
            }
        }

FilterViewmodel.cs

public class FilterViewmodel : INotifyPropertyChanged
{
  public ObservableCollection<FilterControlViewmodel> FilterControls
        {
            get => return _filterControls;
            set
            {
                if (Equals(value, _filterControls)) return;
                _filterControls = value;
                OnPropertyChanged();
            }
        }

FilterControlViewmodel.cs

public class FilterControlViewmodel : INotifyPropertyChanged
{
   private string _filterName = "InitialFilterName";
   public string FilterName
   {
      get => _filterName;
      set
      {
         if (value == _filterName) return;
         _filterName = value;
         OnPropertyChanged();
      }
   }

You should remove the following markup as it creates another instance of FilterControlViewmodel :

<UserControl.DataContext>
   <local:FilterControlViewmodel/>
</UserControl.DataContext>

The FilterControl will then inherit its DataContext from the current item ( FilterControlViewmodel ) in the ItemsControl without you having to set the DataContext property explicitly:

<ItemsControl ItemsSource="{Binding FilterViewmodel.FilterControls}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <filter:FilterControl/>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM