我有一个名为Clan的课程。 Clan中的一个属性是bool Voiced,默认为false。
我有一个观点,ClanUI。它有一个Clan类型的依赖属性。
在VM中,我有一个Clan类型的属性,它作为依赖属性传递给视图:
<UC:ClanUI Clan="{Binding Meilyr}" />
在ClanUI视图中,我有一个图像,它调用VM中的命令。它使用正确的DataContext:
...
<i:InvokeCommandAction Command="{Binding DataContext.ClanVoiced, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}" CommandParameter="{Binding Clan.Name}" />
...
在VM中的那个命令中,我在Meilyr属性上设置了Voiced的值,它作为DP从false传递到视图中。
在视图中,我有一个数据触发器,它应该反映语音的变化。<Style TargetType="{x:Type Border}">
<Setter Property="BorderThickness" Value="2" />
<Style.Triggers>
<DataTrigger Binding="{Binding Clan.Voiced}" Value="false">
<Setter Property="BorderThickness" Value="0" />
</DataTrigger>
</Style.Triggers>
</Style>
我尝试从Voiced默认为true开始,这显示边框厚度为2.因此绑定工作正常。我已经调试了,代码正确地命中了VM,并且Meilyr浊音属性被更改为true,并且正在正确调用OnPropertyChanged。
我不知道为什么,当我在VM中更改DP中的值时,它并未在视图中反映这些更改。
编辑:按要求提供更多代码
这是视图中的边框和图像。单击该图像将调用VM中的命令
<Grid DataContext="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}}">
...
<Border BorderBrush="Red" Margin="5">
<Image Source="{Binding Clan.Image, FallbackValue='../Media/Clans/Meilyr.png'}" Height="40" VerticalAlignment="Center">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseUp">
<i:InvokeCommandAction Command="{Binding DataContext.ClanVoiced, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}" CommandParameter="{Binding Clan.Name}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Image>
<Border.Style>
<Style TargetType="{x:Type Border}">
<Setter Property="BorderThickness" Value="2" />
<Style.Triggers>
<DataTrigger Binding="{Binding Clan.Voiced}" Value="false">
<Setter Property="BorderThickness" Value="0" />
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
</Border>
...
</Grid>
这是xaml.cs中的Dependency属性:
public Clan Clan
{
get { return (Clan)GetValue(ClanProperty); }
set { SetValue(ClanProperty, value); }
}
public static readonly DependencyProperty ClanProperty =
DependencyProperty.Register("Clan", typeof(Clan),
typeof(ClanUI), new PropertyMetadata(null));
在主视图中,以下是我放置视图的方式:
<UC:ClanUI Grid.Column="1" Grid.Row="0" Grid.ColumnSpan="2" Clan="{Binding Meilyr}" />
以下是VM的一些片段:
private Clan _Meilyr = new Clan();
public Clan Meilyr
{
get
{
return _Meilyr;
}
set
{
_Meilyr = value;
OnPropertyChanged("Meilyr");
}
}
...
private ICommand _ClanVoiced;
public ICommand ClanVoiced
{
get
{
if (_ClanVoiced == null)
{
_ClanVoiced = new RelayCommand(ClanVoicedEx, null);
}
return _ClanVoiced;
}
}
private void ClanVoicedEx(object p)
{
if(Clans.FindAll(C => C.Voiced).Count >= 2)
{
//TODO
}
//Clans.First(C => C.Name == p.ToString()).Voiced = true; //<< This is how I will eventually be doing it, the next line was to ensure I was setting the correct thing.
Meilyr.Voiced = true; //When debugging, when I click the image this line is hit, and after it has executed, inspecting Meilyr.Voiced shows it as being true.
}
最后,这里是Clan.cs中的Voiced属性,以及OnPropertyChanged。
private bool _Voiced = false; //<< When I default this to true instead, it displays how I expect in the view. Initial bindings seem to work fine. It just doesn't seem to know when Voiced changes for some reason...
public bool Voiced
{
get
{
return _Voiced;
}
set
{
_Voiced = value;
OnPropertyChanged("Voiced");
}
}
...
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
if (handler.Target is CollectionView)
{
((CollectionView)handler.Target).Refresh();
}
else
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
#endregion
答案 0 :(得分:1)
确保Clan
类实现INotifyPropertyChanged
接口,并在Voiced属性的setter中引发PropertyChanged
事件。
由于您绑定了Clan.Voiced属性,因此定义Meilyr和ClanVoided属性的视图模型类是否实现INotifyPropertyChanged
接口并不重要。
答案 1 :(得分:0)
请你发布ViewModel代码吗。
我假设您正在更新已更改的Clan属性,但未更改Voice属性。换句话说,声音需要是一个属性,它自己的属性改变了事件发生。