【问题标题】:WPF DataTrigger is false but doesn't revert to previous valueWPF DataTrigger 为 false,但不会恢复为以前的值
【发布时间】:2020-03-11 16:35:18
【问题描述】:

我最近创建了一个用户控件,用于通知用户他有多少通知。因为我希望这个用户控件只在有任何通知时才显示自己,所以我创建了一个绑定到布尔值的 DataTrigger,并在没有通知时将可见性设置为折叠。它在开始时工作正常,我的用户控件已折叠,但在我的程序中,我添加了一个通知并在我的 bool 上调用 NotifyPropertyChanged,但由于某些未知原因,用户控件仍然保持隐藏状态。

用户控制

<UserControl.Style>
    <Style TargetType="{x:Type UserControl}">
        <Setter Property="Visibility"
                    Value="Visible">
        </Setter>
        <Style.Triggers>
            <DataTrigger Binding="{Binding HasNotifications}"
                             Value="False">
                <Setter Property="Visibility"
                            Value="Collapsed">
                </Setter>
            </DataTrigger>
        </Style.Triggers>
    </Style>
</UserControl.Style>

数据上下文

private ObservableCollection<Notification> notifications;
public ObservableCollection<Notification> Notifications
{
    get { return notifications; }
}

public bool HasNotifications
{
    get
    {
        return Notifications.Count > 0;
    }
}

public void AddNotification(Notification notificationToAdd)
{
    notifications.Add(notificationToAdd);
    NotifyPropertyChanged(nameof(Notifications));
    NotifyPropertyChanged(nameof(HasNotifications));
}

public event PropertyChangedEventHandler PropertyChanged;

protected virtual void NotifyPropertyChanged(string propertyName)
{
    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

我还尝试使用相反的值设置 DataTrigger(当 HasNotifications 为 true 时将可见性设置为开启),但对我来说也没有成功。

【问题讨论】:

  • 不确定为什么它不起作用,但您甚至可能不需要该属性。带有Binding="{Binding Notifications.Count}" Value="0" 的 DataTrigger 也应该可以工作。
  • 感谢您的建议!摆脱 HasNotifications,现在我绑定到计数。出于某种奇怪的原因,这也解决了我的问题,现在我的控件崩溃并正确重新出现。我仍然很好奇为什么 DataTrigger 不能与我的 bool 一起使用。
  • Binding Notifications.Count 在您的类中没有实现 INotifyPropertyChanged 的​​情况下工作,因为在这种情况下,实现它的是 ObservableCollection。

标签: c# wpf xaml datatrigger


【解决方案1】:

我复制了您的代码并在 3.5 和 4.7 框架下对其进行了测试,并且可以正常工作。我只能在一种情况下重现您的问题,但我在这里猜测是因为该部分不在您的代码示例中。

仅当数据上下文类不继承自INotifyPropertyChanged 时才有效。否则,最小代码示例将按预期工作。

public class MyDataContext :  INotifyPropertyChanged // <= doesn't work if this is missing
{
    private ObservableCollection<Notification> notifications = new ObservableCollection<Notification>();
    public ObservableCollection<Notification> Notifications => notifications;

    public bool HasNotifications=> Notifications.Count > 0;

    public void AddNotification(Notification notificationToAdd)
    {
        notifications.Add(notificationToAdd);
        NotifyPropertyChanged(nameof(Notifications));
        NotifyPropertyChanged(nameof(HasNotifications));
    }

    private ICommand _AddNotification;
    public ICommand AddNotificationCMD => _AddNotification ?? (_AddNotification = new RelayCommand<object>(a => AddNotificationCommand(a)));

    private void AddNotificationCommand(object item)
    {
        AddNotification(new Notification());
    }

    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void NotifyPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

<Window x:Class="WpfApp_3_5_framework_test.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:WpfApp_3_5_framework_test"
    mc:Ignorable="d"
    Title="MainWindow" Height="450" Width="800">
<Grid>
    <local:UserControl1/>
    <Button Content="Add Notification" Command="{Binding AddNotificationCMD}" Height="20" Width="200" />
</Grid>
</Window>

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = new MyDataContext();
    }
}

<UserControl x:Class="WpfApp_3_5_framework_test.UserControl1"
         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:WpfApp_3_5_framework_test"
         mc:Ignorable="d" 
         d:DesignHeight="450" d:DesignWidth="800">
<UserControl.Style>
    <Style TargetType="{x:Type UserControl}">
        <Setter Property="Visibility"
                Value="Visible">
        </Setter>
        <Style.Triggers>
            <DataTrigger Binding="{Binding HasNotifications}"
                         Value="False">
                <Setter Property="Visibility"
                        Value="Collapsed">
                </Setter>
            </DataTrigger>
        </Style.Triggers>
    </Style>
</UserControl.Style>
<Grid>
    <StackPanel>
        <Border Width="100" Height="100" Background="Red"/>
    </StackPanel>
</Grid>
</UserControl>

【讨论】:

  • 不敢相信我忘了添加“:INotifyPropertyChanged”..现在一切都说得通了。我知道我错过了一些东西,但我忘了检查那个。感谢您向我指出这一点。
  • @Swapper 根据我的经验,如果 GUI 没有更新并且您根本无法查明原因,那么 NotifyPropertyChanged 机制通常会出现问题。我使用这个 nuget 包 github.com/Fody/PropertyChanged 来省去自己一遍又一遍地实现它的时间,并减少仅仅因为我忘记复制一行代码而发生错误的可能性......
猜你喜欢
  • 1970-01-01
  • 2013-06-11
  • 2010-09-26
  • 2013-03-16
  • 1970-01-01
  • 2016-02-01
  • 2014-02-08
  • 2021-04-14
  • 2017-06-13
相关资源
最近更新 更多