【问题标题】:Binding To a Custom Control's Dependency Property绑定到自定义控件的依赖属性
【发布时间】:2019-05-26 17:01:04
【问题描述】:

快速概览

我创建了一个自定义控件“InputValuePage”。 我已经用这个名为 InputTitle 的控件注册了一个依赖属性。 在用户控件 InputTitle 中绑定到文本块效果很好,但是当我将此自定义控件用作框架或窗口中的子控件时,我无法使用绑定来设置我的依赖项属性。下面是用于 InputTitle 属性的代码。

自定义控件类代码后面:

public partial class InputValuePage : Page
{
public static readonly DependencyProperty InputTitleProperty  =
    DependencyProperty.Register("InputTitle", typeof(string), typeof(InputValuePage));

public string InputTitle
    {
        get { return (string)GetValue(InputTitleProperty); }
        set { SetValue(InputTitleProperty, value); }
    }

public InputValuePage()
    {
        InitializeComponent();
    }
}

示例用法:

<Frame Grid.Row="2" 
           Grid.ColumnSpan="2"
           Grid.RowSpan="2"
           x:Name="DisFrame">
        <Frame.Content>
            <local:InputValuePage 
                                  InputMessage="This gets set in the control." 
                                  InputTitle="{Binding ElementName=DisFrame, Path=Name}" 
                                  HostWindow="{Binding ElementName=DemoWindow}">
            </local:InputValuePage>
        </Frame.Content>
    </Frame>

为了澄清在 XAML 中设置的三个值都是依赖属性。输入消息和标题可以在提供字符串时成功设置,但数据绑定从未实际设置值。我缺少什么来允许绑定数据?

【问题讨论】:

  • DisFrame 的 Name 属性是否设置在任何地方?什么是演示窗口?请注意,元素名称在 XAML 文件中无效。
  • 在上面的示例用法块中设置了名称“DisFrame”。 DemoWindow 是分配给包含所有控件的父窗口的名称,包括示例用法中显示的框架。我可以毫无问题地对按钮的内容或文本块的文本进行相同的绑定,但是它不适用于自定义控件
  • 指定 x:Name 设置名称属性。如果我用一个按钮替换自定义控件,并为按钮的内容属性指定与上面显示的 InputTitle 完全相同的绑定,那么一切都会按预期工作

标签: c# wpf custom-controls dependency-properties


【解决方案1】:

如果您制作自定义控件,这将非常有效。自定义控件继承自 Control。您的类继承自 Page

我已经用下面的代码试过了:

using System.Windows;
using System.Windows.Controls;

namespace WpfCustomControlLibrary1
{
  public class InputValuePage : Control
  {
    public static readonly DependencyProperty InputTitleProperty =
      DependencyProperty.Register ("InputTitle", typeof (string), typeof (InputValuePage));

    public string InputTitle
    {
      get { return (string)GetValue (InputTitleProperty); }
      set { SetValue (InputTitleProperty, value); }
    }

    static InputValuePage ( )
    {
      DefaultStyleKeyProperty.OverrideMetadata (typeof (InputValuePage), new FrameworkPropertyMetadata (typeof (InputValuePage)));
    }
  }
}

这是我的 Generic.xaml 文件中的 ControlTemplate。请注意,您可以使用 TemplateBinding 访问模板中的属性。

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:WpfCustomControlLibrary1">
  <Style TargetType="{x:Type local:InputValuePage}">
    <Setter Property="Template">
      <Setter.Value>
        <ControlTemplate TargetType="{x:Type local:InputValuePage}">
          <Border Background="{TemplateBinding Background}"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}">

            <TextBlock VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="20" Text="{TemplateBinding InputTitle}"/>

          </Border>
        </ControlTemplate>
      </Setter.Value>
    </Setter>
  </Style>
</ResourceDictionary>

在您创建自定义控件项目时,Visual Studio 会自动生成一个 ControlTemplate。

在我的测试项目中,我将 InputTitle 属性连接到 TextBox 的内容。

<Window x:Class="WpfApp1.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:WpfApp1"
        mc:Ignorable="d"
        xmlns:cc="clr-namespace:WpfCustomControlLibrary1;assembly=WpfCustomControlLibrary1"
        Title="MainWindow" Height="200" Width="200">
  <Grid>
    <Grid.RowDefinitions>
      <RowDefinition Height="Auto"/>
      <RowDefinition Height="*"/>
    </Grid.RowDefinitions>

    <TextBox Grid.Row="0" x:Name="TitleBox" Text="ABC"/>

    <Frame Grid.Row="1" x:Name="DisFrame">
      <Frame.Content>
        <cc:InputValuePage InputTitle="{Binding ElementName=TitleBox, Path=Text}"/>
      </Frame.Content>
    </Frame>

  </Grid>
</Window>

我很确定这也适用于 UserControl,如果您觉得这更容易的话。

显然,它不适用于页面。

【讨论】:

    猜你喜欢
    • 2012-08-29
    • 2012-08-07
    • 1970-01-01
    • 1970-01-01
    • 2011-03-24
    • 1970-01-01
    • 1970-01-01
    • 2011-05-08
    • 2021-08-17
    相关资源
    最近更新 更多