簡體   English   中英

當ObservableCollection中的項目更新時,ItemsControl視圖不會更新

[英]ItemsControl view doesn't updated when an item in ObservableCollection is updated

簡介

嗨,我在這里遇到一個奇怪的問題。 如果我要更新模型(例如,更改IsSelected的值),則我的ItemsControl不會更新視圖。

但是, IsSelected用途之一是,如果該值為true ,則MusicalNotationBox的背景(UserControl)更改為藍色,如果為false則將其更改為透明。

很多人問: 為什么不使用觸發器,例如 Focus for IsSelected 因為它不僅用於“視覺”目的。 我有一個命令,可以更改VM的MusicalNotations中每個MusicalNotation對象的某些Property (例如Note的Octave),該IsSelected==true (支持IsSelected==true ),所以我認為我需要在模型中使用IsSelected 但這不是這里的問題,因此請不要僅就此問題回答。

問題是 :

  1. 模型屬性已成功更改(已檢查並驗證),但似乎視圖未更改。
  2. 如果我使用UserControl的單數形式 ,例如<c:MusicalNotationBox DataContext={Binding}/> (ofc及其在VM中的朋友,也稱為正確屬性),則它會完美同步 因此,我不太確定問題出在OC上。
  3. 更新:例如,如果我每次單擊都會創建一個MouseBinding,然后將一個新的MusicalNotation添加到列表中,那么視圖也會更新。

我已經閱讀了“ Observable Collection不會更新ItemsControl`,但仍然找不到令人滿意的答案”(在Google和此處)的幾個主題。

這是我的代碼(為了清楚起見,代碼可能會被修剪(...)):

模型

public class MusicalNotation : ... INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    ...
    private bool _isSelected;
    ...
    public bool IsSelected
    {
        get { return _isSelected; }
        set { _isSelected = value; NotifyPropertyChanged("IsSelected"); }
    }
    ...
    public MusicalNotation()
    {
        ...
        IsSelected = false;
    }
    ...
    private void NotifyPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

查看模型

public class MainWindowModelView : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    private ObservableCollection<MusicalNotation> _musicalNotations;
    ...
    public ObservableCollection<MusicalNotation> MusicalNotations
    {
        get { return _musicalNotations; }
        set { _musicalNotations = value; NotifyPropertyChanged("MusicalNotations"); }
    }

    public MainWindowModelView()
    {
        ...
        MusicalNotations = new ObservableCollection<MusicalNotation>();

        //Direct initialization for testing purpose
        MusicalNotations.Add(MusicalNotation.GetEmptyNote(new TimeSignature(4, 4)));
        MusicalNotations.Add(MusicalNotation.GetEmptyNote(new TimeSignature(4, 4)));

        foreach (MusicalNotation item in MusicalNotations)
        {
            item.IsSelected = true;
        }
    }

    private void NotifyPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

視圖

<Window ...>
<Window.Resources>

</Window.Resources>
<Window.InputBindings>
    ...
</Window.InputBindings>
<Grid>
    ...        
    <ItemsControl Grid.Column="0" Grid.Row="0" ItemsSource="{Binding MusicalNotations, Mode=OneWay}"
                  HorizontalAlignment="Center" VerticalAlignment="Center">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <StackPanel IsItemsHost="True" Orientation="Horizontal"/>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <c:MusicalNotationBox/>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
</Grid>

謝謝。

更新,我的MusicalNotationBox XAML

<UserControl x:Class="NumberedMusicScoresUserControl.MusicalNotationBox"
         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:NumberedMusicScoresUserControl.MusicalNotationBoxProperties"
         mc:Ignorable="d">
<UserControl.Resources>
    <local:DotConverter x:Key="DotConverter"/>
    <local:NoteConverter x:Key="NoteConverter"/>
    <local:AccidentalConverter x:Key="AccidentalConverter"/>
    <local:IsSelectedConverter x:Key="IsSelectedConverter"/>
</UserControl.Resources>

<Grid x:Name="grid" Margin="10,5,10,5"
      HorizontalAlignment="Center" VerticalAlignment="Center"
      Background="{Binding Path=MusicalNotation.IsSelected, Converter={StaticResource IsSelectedConverter}, Mode=OneWay}">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto"/>
        <ColumnDefinition Width="Auto"/>
        <ColumnDefinition Width="Auto"/>
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>

    <TextBlock Grid.Column="0" Grid.Row="1"
               Text="b"
               Visibility="{Binding Path=MusicalNotation.Accidental, Converter={StaticResource AccidentalConverter}, ConverterParameter=FL, Mode=OneWay}" 
               FontSize="15" FontFamily="CourierNew" 
               HorizontalAlignment="Center" VerticalAlignment="Center"/>
    <Path Grid.Column="1" Grid.Row="1" Stroke="Black" StrokeThickness="1" Stretch="Fill"
          Visibility="{Binding Path=MusicalNotation.Accidental, Converter={StaticResource AccidentalConverter}, ConverterParameter=SP, Mode=OneWay}" >
        <Path.Data>
            <LineGeometry StartPoint="1,0" EndPoint="0,1">
                <LineGeometry.Transform>
                    <RotateTransform CenterX="0" CenterY="0" Angle="30"/>
                </LineGeometry.Transform>
            </LineGeometry>
        </Path.Data>
    </Path>
    <TextBlock Grid.Column="1" Grid.Row="1" 
               Text="{Binding Path=MusicalNotation.Note, Converter={StaticResource NoteConverter}, Mode=OneWay}" 
               FontSize="15" FontFamily="CourierNew" 
               HorizontalAlignment="Center" VerticalAlignment="Center"
               Margin="2.5,0,2.5,0"/>
    <ItemsControl Grid.Column="1" Grid.Row="0" 
                  ItemsSource="{Binding Path=MusicalNotation.Octave, Converter={StaticResource DotConverter}, ConverterParameter=TOP, Mode=OneWay}">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <StackPanel IsItemsHost="True"/>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <Ellipse HorizontalAlignment="Center" VerticalAlignment="Top"
                         Margin="{Binding Margin}" Fill="{Binding Fill}" 
                         Width="{Binding Diameter}" Height="{Binding Diameter}"/>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
    <ItemsControl Grid.Column="1" Grid.Row="2" 
                  ItemsSource="{Binding Path=MusicalNotation.Octave, Converter={StaticResource DotConverter}, ConverterParameter=BOT, Mode=OneWay}">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <StackPanel IsItemsHost="True"/>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <Ellipse HorizontalAlignment="Center" VerticalAlignment="Bottom"
                         Margin="{Binding Margin}" Fill="{Binding Fill}" 
                         Width="{Binding Diameter}" Height="{Binding Diameter}"/>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
    <ItemsControl Grid.Column="2" Grid.Row="1" 
                  ItemsSource="{Binding Path=MusicalNotation.Dot, Converter={StaticResource DotConverter}, ConverterParameter=RIGHT, Mode=OneWay}">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <StackPanel Orientation="Horizontal" IsItemsHost="True"/>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <Ellipse HorizontalAlignment="Left" VerticalAlignment="Center"
                         Margin="{Binding Margin}" Fill="{Binding Fill}" 
                         Width="{Binding Diameter}" Height="{Binding Diameter}"/>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
</Grid>

(我不包括它,因為我認為,如果“單數”正確,那么我的UserControl也正確。不過,可能是錯誤的。)

用戶控件的DataContextMusicalNotation對象,因此在綁定而不是使用

Background="{Binding Path=MusicalNotation.IsSelected, Converter={StaticResource ....

只是使用

Background="{Binding Path=IsSelected, Converter={StaticResource ....

由於您尚未在xaml中為所選項目或IsSelected指定任何綁定,因此,當在VM中更改屬性時,視圖未更新。 為了更新視圖,您將必須為ItemsControl的SelectedItem屬性提供一個綁定。

從綁定中刪除MusicalNotation前綴。

{Binding Path=IsSelected, ...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM