在依赖项 属性 中更新 属性 未显示在视图中

Updating property within Dependency property doesn't show within view

我有一个 class,叫做 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 中的那个命令中,我在 属性 Meil​​yr 上设置了 Voiced 的值,它作为 DP 从假到真传递到视图中。

在视图中,我有一个数据触发器,它应该反映声音的变化。

<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 voiced 属性 被更改为 true,并且正确调用 On属性Changed。

我不知道为什么,当我从 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 中的依赖项 属性:

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 中的浊音 属性,以及 On属性Changed.

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

你能post ViewModel 代码吗?

我假设您更新的是 Clan 属性 已更改但语音 属性 未更改。换句话说,有声需要是一个 属性,它自己 属性 改变了事件触发。

确保 Clan class 实现了 INotifyPropertyChanged 接口并在有声 属性 的 setter 中引发了 PropertyChanged 事件].

由于您要绑定到 Clan.Voiced 属性,因此定义 Meil​​yr 和 ClanVoided 属性的视图模型 class 是否实现 INotifyPropertyChanged 并不重要接口。