【发布时间】:2018-01-04 16:11:02
【问题描述】:
我看了又长又硬,卡住了。我正在尝试通过 Window 的绑定将参数从 Window 传递给 UserControl1。
在 MainWindow 中,UserControl1 包含两次,一次是通过 MyValue 上的绑定传递参数 MyCustom,另一次是使用文字。使用绑定传递对 UserControl1 没有影响。 MyCustom 依赖属性没有改变。使用文字,它按预期工作。
我很困惑。我已经复制了https://stackoverflow.com/a/21718694/468523 中的示例,但没有任何乐趣。我一定缺少一些简单的东西。
对我复制的所有代码感到抱歉,但魔鬼往往在细节中..
MainWindow.xaml
<Window x:Class="MyParamaterizedTest3.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:MyParamaterizedTest3"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525"
DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Grid HorizontalAlignment="Center" VerticalAlignment="Center">
<StackPanel>
<Rectangle Height="20"/>
<local:UserControl1 MyCustom="{Binding MyValue, UpdateSourceTrigger=PropertyChanged}"/>
<Rectangle Height="20"/>
<local:UserControl1 MyCustom="Literal Stuff"/>
<Rectangle Height="20"/>
<StackPanel Orientation="Horizontal">
<TextBlock Text="MainWindow: "/>
<TextBlock Text="{Binding MyValue, UpdateSourceTrigger=PropertyChanged}"/>
</StackPanel>
</StackPanel>
</Grid>
</Window>
MainWindow.xaml.cs
namespace MyParamaterizedTest3
{
public partial class MainWindow : INotifyPropertyChanged
{
public MainWindow()
{
InitializeComponent();
}
public string MyValue { get => _myValue; set => SetField(ref _myValue, value); }
private string _myValue= "First things first";
public event PropertyChangedEventHandler PropertyChanged;
protected bool SetField<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
{
if (EqualityComparer<T>.Default.Equals(field, value)) { return false; }
field = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
return true;
}
}
}
UserControl1.xaml(以下已更正)
<UserControl x:Class="MyParamaterizedTest3.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:MyParamaterizedTest3"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
>
<Grid HorizontalAlignment="Center" VerticalAlignment="Center">
<Border BorderThickness="3" BorderBrush="Black">
<StackPanel>
<TextBlock Text="{Binding MyCustom, UpdateSourceTrigger=PropertyChanged, FallbackValue=mycustom}"></TextBlock>
</StackPanel>
</Border>
</Grid>
</UserControl>
UserControl1.xaml.cs(以下更正)
namespace MyParamaterizedTest3
{
public partial class UserControl1 : INotifyPropertyChanged
{
public UserControl1()
{
InitializeComponent();
}
public static readonly DependencyProperty MyCustomProperty =
DependencyProperty.Register("MyCustom", typeof(string), typeof(UserControl1));
public string MyCustom
{
get
{
return this.GetValue(MyCustomProperty) as string;
}
set
{
this.SetValue(MyCustomProperty, value);
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected bool SetField<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
{
if (EqualityComparer<T>.Default.Equals(field, value)) { return false; }
field = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
return true;
}
}
}
已更正 UserControl1.xaml(根据 Ed Plunkett)
<UserControl x:Class="MyParamaterizedTest3.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"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300"
>
<Grid HorizontalAlignment="Center" VerticalAlignment="Center">
<Border BorderThickness="3" BorderBrush="Black">
<StackPanel>
<TextBlock Text="{Binding MyCustom, RelativeSource={RelativeSource AncestorType=UserControl}, FallbackValue=mycustom}"></TextBlock>
</StackPanel>
</Border>
</Grid>
</UserControl>
已更正 UserControl1.xaml.cs(根据 Ed Plunkett)
<UserControl x:Class="MyParamaterizedTest3.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"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300"
>
<Grid HorizontalAlignment="Center" VerticalAlignment="Center">
<Border BorderThickness="3" BorderBrush="Black">
<StackPanel>
<TextBlock Text="{Binding MyCustom, RelativeSource={RelativeSource AncestorType=UserControl}, FallbackValue=mycustom}"></TextBlock>
</StackPanel>
</Border>
</Grid>
</UserControl>
【问题讨论】:
-
你不需要 INPC 的东西。依赖属性不使用它,用户控件应该使用依赖属性。您的问题是您通过踩到 DataContext 破坏了用户控件上的所有绑定。不要那样做。在 UC XAML 中使用相对源绑定。您所遵循的示例并没有告诉您破坏 DataContext。
-
你是对的,在这种情况下是不必要的。但已删除,仍然无法正常工作。
-
所以,我还删除了用户控件中的 DataContext 设置,但随后用户控件 xaml 绑定到 MyCustom 中断了。
-
如上:“在 UC XAML 中使用相对源绑定”。详情见答案。