Introduction :
Hi, I meet a weird problem here. My ItemsControl
doesn't update the view if I am updating the model (eg changing the value of IsSelected
).
One of IsSelected
purpose however, is, if the value is true
, then the Background of the MusicalNotationBox
(UserControl) is changed to blue, and if it's false
then it's changed back to transparent.
A lot of person asked : Why not using trigger such as
Focus
forIsSelected
? Because it's not just for "visual" purposes. I have a Command which to change certainProperty
(for example Note's Octave) of eachMusicalNotation
object in VM'sMusicalNotations
, whichIsSelected==true
(support multiselection), so I think I needIsSelected
in the model. But this is not the problem here, so please no answer solely on this matter.
The problem is :
<c:MusicalNotationBox DataContext={Binding}/>
(ofc along with it's friends aka correct properties in the VM), it synced perfectly . So, I'm not quite sure where the problem lies with the OC. MusicalNotation
added to the list, then, the view is also updated. I have read several topic (google and here) on "Observable Collection doesn't update the ItemsControl`, but still found no satisfying answer.
Here's my code (code may trimmed (...) for clarity sake) :
MODEL
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));
}
}
VIEW MODEL
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));
}
}
}
VIEW
<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>
Thanks.
UPDATE, My 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>
(I didn't include it since, I think, if the "singular" one is correct, then my UserControl is correct as well. Might be wrong though.)
The DataContext
for your user control is the MusicalNotation
object, so while binding instead of using
Background="{Binding Path=MusicalNotation.IsSelected, Converter={StaticResource ....
just use
Background="{Binding Path=IsSelected, Converter={StaticResource ....
As you haven't specified any binding for the selected item or for the IsSelected in your xaml, that's why view is not being updated when the property is changed in the VM. For updating the view you will have to provide a binding for SelectedItem property of ItemsControl.
从绑定中删除MusicalNotation前缀。
{Binding Path=IsSelected, ...
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.