数据触发器未触发

时间:2009-10-16 05:39:08

标签: 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();
    }
}

这是我在视图中创建用户控件:

<localControls:BusyDialog x:Name="busyControl"
                               Grid.Row="0" 
                               IsBusy="{Binding IsWorking}"
                               BusyText="{Binding WorkingText}">
</localControls:BusyDialog>

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

我还尝试设置用户控件绑定,如下所示:

<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>

2 个答案:

答案 0 :(得分:2)

您需要在视图模型中实现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执行相同的操作。希望有所帮助。

答案 1 :(得分:0)

触发器中的绑定对我来说似乎很奇怪。试试这个:

<Trigger Property="IsBusy" Value="true">
    <Setter Property="Visibility" Value="Visible" />
    <Setter Property="Opacity" Value=".3" />
</Trigger>

当我阅读你的代码时,逻辑对我来说并不完全合理。 0.3不透明度对于必须可见的控件是否足够?请记住通过Controls XAML设置默认行为,并使用触发器仅修改适合该状态的值。

我想说的是你的触发器上的IsEnabled setter。这可能很好地在主UserControl中设置,因为当前控件只能在隐藏控件时被启用,当它被显示为禁用时。

这有意义吗?希望这有帮助!