19

いくつかの DependencyProperties を使用して UserControl を作成しました (この例では、1 つの文字列プロパティのみ)。ユーザーコントロールをインスタンス化すると、ユーザーコントロールのプロパティを設定でき、期待どおりに表示されます。静的テキストを Binding に置き換えようとすると、何も表示されません。

私の UserControl は次のようになります。

<User Control x:Class="TestUserControBinding.MyUserControl"
             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="30" d:DesignWidth="100">
    <Grid>
    <Label Content="{Binding MyText}"/>
  </Grid>
</UserControl>

コードビハインドは次のとおりです。

namespace TestUserControBinding {

  public partial class MyUserControl : UserControl {
    public MyUserControl() {
      InitializeComponent();
      this.DataContext = this;
    }

    public static readonly DependencyProperty MyTextProperty = 
                   DependencyProperty.Register(
                         "MyText", 
                          typeof(string), 
                          typeof(MyUserControl));

    public string MyText {
      get {
        return (string)GetValue(MyTextProperty);
      }
      set {
        SetValue(MyTextProperty, value);
      }
    }// MyText

  }
}

MainWindow でこれを試してみると、すべてが期待どおりです。

<Window x:Class="TestUserControBinding.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:TestUserControBinding"
        Title="MainWindow" Height="350" Width="525">
  <StackPanel>
    <local:MyUserControl MyText="Hello World!"/>
  </StackPanel>
</Window>

しかし、これはうまくいきません:

<Window x:Class="TestUserControBinding.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:TestUserControBinding"
        Title="MainWindow" Height="350" Width="525">
  <StackPanel>
    <local:MyUserControl MyText="{Binding Path=Text}"/>
    <Label Content="{Binding Path=Text}"/>
  </StackPanel>
</Window>

ラベルの動作は正しいので、プロパティ「テキスト」に問題はありません

私の間違いは何ですか?何時間も考えますが、忘れたものは何も見つかりません。

4

2 に答える 2

28

で次のバインディングを使用しますUserControl

<Label Content="{Binding MyText}"/>

テキストを MyText プロパティに直接設定する方法がわかりません。DataContextこれを機能させるには、UserControlどこかで を設定する必要があります。

とにかく、このバインディングが問題です - あなたのシナリオを理解しているので、必ずしも MyText プロパティを持つとは限らないため、DataContextのにバインドしたくありません。それ自体、特に作成UserControlした にバインドします。そのためには、次のようなバインディングを使用する必要があります。UserControlDependencyPropertyRelativeSource

<Label Content="{Binding RelativeSource={RelativeSource AncestorType={x:Type local:MyUserControl}}, Path=MyText}"/>

これにより、ビジュアル ツリーを上に移動して MyUserControl に移動し、そこで MyText プロパティを見つけます。に依存せずDataContext、 を配置する場所に基づいて変化しますUserControl

この場合、 でlocal定義する必要がある名前空間を参照しますUserControl

<UserControl x:Class="TestUserControBinding.MyUserControl"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:local="clr-namespace:TestUserControBinding"
         ...>

そして、2番目の例はその時点で機能するはずです。

于 2013-06-07T13:57:39.417 に答える
5

DataContexts の設定方法について誤解があります。これはあなたに不利に働いています...

最終的MyTextに、ユーザー コントロールへのバインディングは、コントロールの依存関係プロパティではなく、ページの依存関係プロパティにバインドされ、プロパティはありません。MyTextDataContextMyText

説明させてください


説明ユーザー コントロールをメイン ページに配置すると、そのコントロールの親DataContext( StackPanel) が継承されます。親DataContextが設定されていない場合は、ページに到達するまで、チェーンを上に移動してStackPanel親の親DataContext(ad Infinium) に移動しますDataContext(この例では、設定され有効です)。

メインページでバインドする場合など、メインページの DataContext でプロパティを<local:MyUserControl MyText="{Binding Path=Text}"/>検索しText、依存関係プロパティMyTextをその値に設定します。これはあなたが期待するものであり、うまくいきます!

現在 の状態 したがって、コード内のユーザー コントロールの状態はこれでありDataContext、ページにバインドされ、DataContext依存MyText関係プロパティが設定されています。しかし、内部統制のバインドはMyText失敗します。なんで?

ユーザー コントロールには親のデータ コンテキストがあり、そのMyTextデータ コンテキストのプロパティにバインドするようコントロールに要求しています。そのようなプロパティはなく、失敗します。


解像度

コントロールのインスタンスMyTextにバインドしてプロパティから値を取得するには、次のようにコントロールに名前 (要素名) を付けるだけです。

<User Control x:Class="TestUserControBinding.MyUserControl"
             ...
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             x:Name="ucMyUserControl"

次に、バインディングをデフォルトから離れて、 と呼ばれる elementnamed 名前付きインスタンスに適切にDataContextパスますucMyUserControl。そのような:

  <Label Content="{Binding MyText, ElementName=ucMyUserControl }"/>

コントロールに名前を付けた後、VS2017/2019 は実際にインテリセンスを行うことに注意してくださいElementName


Parents データ コンテキストを使用するだけの副作用

前述の解決策がない場合の元の状況の副作用は、ユーザー コントロールのバインディングを にバインドするだけでText、バインディングがページのデータ コンテキストにデフォルト設定されているため機能することです。微妙...

<User Control x:Class="TestUserControBinding.MyUserControl"
             mc:Ignorable="d" 
             d:DesignHeight="30" d:DesignWidth="100">
 <Grid>
    <Label Content="{Binding Text}"/>

それは機能し、技術的には依存関係プロパティを削除できます。コントロールがプロジェクトの外部で使用されない場合、悪影響を与えずに他の名前付きプロパティにバインドするように設計できます。

次に、内部 XAML をページに貼り付けたのように、すべてのユーザー コントロールがメイン ページの事実上のサブ コントロールになる可能性があります。

于 2019-10-02T14:52:40.130 に答える