如何在 WPF 中使用 Caliburn.Micro 和 UserControl 的绑定?

How to use binding in WPF with Caliburn.Micro and with UserControl?

我创建了一个带有一些字段的用户控件。我想使用它并将数据绑定到这些字段。其中大部分是静态值,但 DataValue 属性 来自 MainView 的一个 属性。 我的代码:

DataDisplayer.xaml
<UserControl x:Class="TabletMachineAccess.Controls.DataDisplayer"
             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:local="clr-namespace:TabletMachineAccess.Controls"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             x:Name="dataDisplayer"
             MaxHeight="100"
             mc:Ignorable="d">

    <Border Height="auto"
            Margin="5"
            Padding="5,2,5,2"
            BorderBrush="Gray"
            BorderThickness="2"
            CornerRadius="5">
        <StackPanel Orientation="Vertical">
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="{Binding DataType}" />
                <TextBlock Text=":" />
            </StackPanel>
            <Separator Style="{StaticResource BasicSeparator}" />
            <TextBlock Margin="0,0,0,0"
                       HorizontalAlignment="Center"
                       FontWeight="Bold"
                       Text="{Binding Path=DataValue,
                                      ElementName=dataDisplayer}" />
            <StackPanel HorizontalAlignment="Right" Orientation="Horizontal">
                <TextBlock FontWeight="ExtraLight" Text="(" />
                <TextBlock FontWeight="ExtraLight" Text="{Binding UnitText}" />
                <TextBlock FontWeight="ExtraLight" Text=")" />
            </StackPanel>
        </StackPanel>
    </Border>
</UserControl>
DataDisplayer.xaml.cs
public partial class DataDisplayer : UserControl
{
    public double DataValue
    {
        get { return (double)GetValue(DataValueProperty); }
        set { SetValue(DataValueProperty, value); }
    }

    // Using a DependencyProperty as the backing store for DataValue.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty DataValueProperty =
        DependencyProperty.Register("DataValue", typeof(double), typeof(DataDisplayer), new PropertyMetadata(9.9));

    public string DataType
    {
        get; set;
    }

    public string UnitText
    {
        get; set;
    }

    public DataDisplayer()
    {
        InitializeComponent();
        this.DataContext = this;
    }
}
我尝试在 MainView.xaml 中这样使用它
 <controls:DataDisplayer Grid.Row="1"
    Grid.Column="0"
    DataType="{x:Static res:Strings.PVUpper}"
    DataValue="{Binding PVUpper}"
    UnitText="{x:Static res:Strings.KgUnit}" />
我的 MainViewModel.cs 里有这个
public double PVUpper { get; set; }

对于那些从 res:Strings 获取数据的属性可以正常工作并显示正确的值,但 DataValue 属性 始终显示 DependencyProperty (9.9) 的默认值。 PVUpper 的值在 ViewModel 中每秒都在变化,所以我希望在 View 上也能看到这种变化。

问题是绑定的 DataContex 错误。您将 DataDisplayerDataContext-属性 设置为自身

public DataDisplayer()
{
    InitializeComponent();
    this.DataContext = this;
}

因此绑定 DataValue="{Binding PVUpper}" 试图在您的 DataDisplayer 实例上找到名称为 PVUpper 的 属性,这当然不会成功。

所以你不应该做 this.DataContext = this; 而只是让 DataContext 保持不变(你的控件将继承其父控件的数据上下文)。 您还需要更改 DataDisplayer.xaml 中的绑定以解决更改后的 DataContext。

但是您可以简单地向所有绑定添加一个 ElementName=dataDisplayer 以绑定到您的 DataDisplayer 实例。

例如

<TextBlock FontWeight="ExtraLight" Text="{Binding UnitText}" />

变成

<TextBlock FontWeight="ExtraLight" Text="{Binding UnitText, ElementName=dataDisplayer}" />