我有一个简单的用户控件,其中包含一个图像,我希望根据父级中的属性(可能是另一个UC或窗口)更改其源。 UC的简化版本如下所示
<UserControl x:Class="Test.Controls.DualStateButton" ... x:Name="root">
<Grid>
<Image Height="{Binding Height, ElementName=root}" Stretch="Fill" Width="{Binding Width, ElementName=root}">
<Image.Style>
<Style TargetType="{x:Type Image}">
<Setter Property="Source" Value="{Binding ImageOff, ElementName=root}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding State}" Value="True">
<Setter Property="Source" Value="{Binding ImageOn, ElementName=root}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
</Grid>
</UserControl>
高度,宽度,ImageOff,ImageOn和State都是UC上的依赖属性。 UC没有DataContext集,因此它应该继承父级。我尝试做的是类似于以下内容,其中UC中的State绑定到Window的DualState属性。
<Window x:Class="Test.MainWindow" DataContext="{Binding RelativeSource={RelativeSource Self}}">
...
<Grid>
<local:DualStateButton State="{Binding DualState}" Height="100" ImageOff="{StaticResource ButtonUp}" ImageOn="{StaticResource ButtonDown}" Width="100"/>
</Grid>
</Window>
然而,我得到的是一个错误,说“状态”和“#39;在&#39; object&#39;上找不到的属性&#39;&#39;&#39; MainWindow&#39;,所以它似乎正在接受绑定&#39; State&#39;在UC中,并没有将它分配给Window的DualState属性。有人可以对我做错了什么有所了解吗?
如果我通过代码或XAML(作为bool值)在UC上设置State属性,它可以正常工作。州DP定义如下。
public static readonly DependencyProperty StateProperty =
DependencyProperty.Register("State", typeof(bool), typeof(DualStateButton),
new PropertyMetadata(false));
public bool State
{
get { return (bool)GetValue(StateProperty); }
set { SetValue(StateProperty, value); }
}
数据类型是否需要是绑定或某种东西才能使其正常工作?
答案 0 :(得分:3)
DataTrigger的DataContext设置为窗口,这就是它查看&#34; State&#34;窗口的原因。您只需要告诉绑定State是否在用户控件上。试试这个:
<DataTrigger Binding="{Binding Path=State, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}" Value="True">
这是一个完整的例子:
MainWindow.xaml
<Window x:Class="WpfApplication89.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:WpfApplication89"
mc:Ignorable="d"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
Title="MainWindow" Height="350" Width="525">
<StackPanel>
<local:UserControl1 State="{Binding Path=DualState}" />
<CheckBox Content="DualState" IsChecked="{Binding DualState}" />
</StackPanel>
</Window>
MainWindow.xaml.cs
using System.Windows;
namespace WpfApplication89
{
public partial class MainWindow : Window
{
public static readonly DependencyProperty DualStateProperty = DependencyProperty.Register("DualState", typeof(bool), typeof(MainWindow), new PropertyMetadata(false));
public bool DualState
{
get { return (bool)GetValue(DualStateProperty); }
set { SetValue(DualStateProperty, value); }
}
public MainWindow()
{
InitializeComponent();
}
}
}
UserControl1.xaml
<UserControl x:Class="WpfApplication89.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:WpfApplication89"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<TextBlock Text="User Control 1">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Background" Value="Beige" />
<Style.Triggers>
<DataTrigger Binding="{Binding Path=State, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}" Value="true">
<Setter Property="Background" Value="Red" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</Grid>
</UserControl>
UserControl1.xaml.cs
using System.Windows;
using System.Windows.Controls;
namespace WpfApplication89
{
public partial class UserControl1 : UserControl
{
public static readonly DependencyProperty StateProperty = DependencyProperty.Register("State", typeof(bool), typeof(UserControl1), new PropertyMetadata(false));
public bool State
{
get { return (bool)GetValue(StateProperty); }
set { SetValue(StateProperty, value); }
}
public UserControl1()
{
InitializeComponent();
}
}
}
MainWindow.xaml.cs(INotifyPropertyChanged version)
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows;
namespace WpfApplication89
{
public partial class MainWindow : Window, INotifyPropertyChanged
{
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
protected bool SetProperty<T>(ref T field, T value, [CallerMemberName]string name = null)
{
if (Equals(field, value))
{
return false;
}
field = value;
this.OnPropertyChanged(name);
return true;
}
protected void OnPropertyChanged([CallerMemberName]string name = null)
{
var handler = this.PropertyChanged;
handler?.Invoke(this, new PropertyChangedEventArgs(name));
}
#endregion
#region Property bool DualState
private bool _DualState;
public bool DualState { get { return _DualState; } set { SetProperty(ref _DualState, value); } }
#endregion
public MainWindow()
{
InitializeComponent();
}
}
}