wpf - 数据触发器未触发

标签 wpf data-binding mvvm datatrigger

我有一个自定义用户控件,它公开了两个依赖属性 IsBusyBusyText .

我想要的是当 IsBusy 设置为 true 时控件出现...这是用户控件的 xaml

<UserControl x:Class="MyNamespace.BusyDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:MyNamespace"  
Height="Auto" 
Width="Auto"
x:Name="busyControl">
<Grid Panel.ZIndex="10">
    <Border Opacity=".2">
        <Border.Background>
            <RadialGradientBrush>
                <GradientStop Color="#FF000000" Offset="0.59"/>
                <GradientStop Color="#FFB6B6B6" Offset="0"/>
            </RadialGradientBrush>
        </Border.Background>
    </Border>
    <Border VerticalAlignment="Center" 
                    HorizontalAlignment="Center"
                    BorderThickness="2"
                    BorderBrush="Gray">     
        <TextBlock Text="{Binding RelativeSource={RelativeSource FindAncestor,
                                                                 AncestorType=controls:BusyDialog},
                                                                 Path=BusyText}"
                   Opacity="1" 
                   Margin="20,10,20,10"/>
    </Border>
    <Grid.Style>
        <Style TargetType="Grid">
            <Setter Property="Visibility" Value="Hidden"/>
            <Style.Triggers>
                <DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType=controls:BusyDialog},Path=IsBusy}" Value="True">
                    <Setter Property="Opacity" Value=".3" />
                    <Setter Property="IsEnabled" Value="False" />
                    <Setter Property="Visibility" Value="Visible"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </Grid.Style>
</Grid>

这是后面的代码
public partial class BusyDialog : UserControl
{
    #region Dependency Properties

    public string BusyText
    {
        get { return (string)GetValue(BusyTextProperty); }
        set { SetValue(BusyTextProperty, value); }
    }

    public bool IsBusy
    {
        get{ return (bool)GetValue(IsBusyProperty); }
        set { SetValue(IsBusyProperty, value); }
    }

    public static readonly DependencyProperty IsBusyProperty =
        DependencyProperty.Register(
            "IsBusy", 
            typeof(bool), 
            typeof(BusyControl), 
            new FrameworkPropertyMetadata(
                false, 
                FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));

    public static readonly DependencyProperty BusyTextProperty =
        DependencyProperty.Register(
            "BusyText", 
            typeof(string), 
            typeof(BusyControl), 
            new FrameworkPropertyMetadata(
                string.Empty, 
                FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
    #endregion

    public BusyDialog ()
    {
        InitializeComponent();
    }
}

这是我在 View 中创建用户控件:
<localControls:BusyDialog x:Name="busyControl"
                               Grid.Row="0" 
                               IsBusy="{Binding IsWorking}"
                               BusyText="{Binding WorkingText}">
</localControls:BusyDialog>

我的代码有什么问题吗?每当我在 ViewModel 中设置 IsWorking 属性时,控件都不会按预期显示!

我还尝试像这样设置用户控件绑定(bind):
<UserControl x:Class="MyNamespace.BusyDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:MyNamespace"  
Height="Auto" 
Width="Auto"
x:Name="busyControl">
<Grid Panel.ZIndex="10">
    <Border Opacity=".2">
        <Border.Background>
            <RadialGradientBrush>
                <GradientStop Color="#FF000000" Offset="0.59"/>
                <GradientStop Color="#FFB6B6B6" Offset="0"/>
            </RadialGradientBrush>
        </Border.Background>
    </Border>
    <Border VerticalAlignment="Center" 
                    HorizontalAlignment="Center"
                    BorderThickness="2"
                    BorderBrush="Gray">     
        <TextBlock Text="{Binding ElementName=busyControl, Path=BusyText}"
                   Opacity="1" 
                   Margin="20,10,20,10"/>
    </Border>
    <Grid.Style>
        <Style TargetType="Grid">
            <Setter Property="Visibility" Value="Hidden"/>
            <Style.Triggers>
                <DataTrigger Binding="{Binding ElementName=busyControl,Path=IsBusy}" Value="True">
                    <Setter Property="Opacity" Value=".3" />
                    <Setter Property="IsEnabled" Value="False" />
                    <Setter Property="Visibility" Value="Visible"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </Grid.Style>
</Grid>

最佳答案

您需要在 View 模型中实现 INotifyPropertyChanged。

public class WorkingViewModel : INotifyPropertyChanged
{
    // ...

    private bool _isWorking;
    public bool IsWorking
    {
        get{ return _isWorking; }
        set {
                _isWorking = value;
                RaisePropertyChanged("IsWorking");
            }
    }

    // ...
    /// <summary>
    /// Occurs when a property value changes.
    /// </summary>
    public event PropertyChangedEventHandler PropertyChanged;

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

    // ...
}

这样,当您的 IsWorking 更改时,它将更新您的 BusyDialog 控件中的 IsBusy。
<localControls:BusyDialog x:Name="busyControl"
                               Grid.Row="0" 
                               IsBusy="{Binding IsWorking}"
                               BusyText="{Binding WorkingText}">
</localControls:BusyDialog>

如果您也打算更改它,请确保对您的 WorkingText 执行相同的操作。希望有帮助。

关于wpf - 数据触发器未触发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1576261/

相关文章:

c# - 如何在 DataContext 略有不同的情况下重用 UserControl?

c# - 使用 System.ComponentModel.DataAnnotations.Validator 验证属性

c# - 为什么我的模板的文本框无法绑定(bind)

wpf - MVVM 中的绑定(bind) slider 值

c# - shell 中的 stderr 和日志文件中的副本

c# - 如何禁用新行的特定 DataGrid 单元格

WinForms多线程数据绑定(bind)场景,最佳实践?

WPF ItemsControl - ViewModel 上的命令未从 ItemsControl 中触发

android - android 绑定(bind)应用程序中的自定义事件属性 :onMyEvent

javascript - 具有多对多关系的 Knockout JS ObservableArray