1

ウィンドウからユーザー コントロールへのプロパティ値の継承を利用しようとしています。私が理解している限りでは、添付の DependencyProperty を (FrameworkPropertyMetadataOptions.Inherits オプションと組み合わせて) 宣言することでこれを実現できます。

MainWindow.xaml:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525" xmlns:my="clr-namespace:WpfApplication1" Name="BobWindow">
    <Grid>
        <Label Content="MainWindow" />
        <TextBox Height="23" HorizontalAlignment="Left" Margin="85,2,0,0" Name="textBox1" VerticalAlignment="Top" Width="120" Text="{Binding Path=Test, ElementName=BobWindow}" />
        <my:UserControl1 HorizontalAlignment="Left" Margin="157,108,0,0" x:Name="userControl11" VerticalAlignment="Top" />
    </Grid>
</Window>

MainWindow.xaml.cs:

using System;
using System.Windows;

namespace WpfApplication1
{
    public partial class MainWindow : Window
    {
        public static readonly DependencyProperty TestProperty = DependencyProperty.RegisterAttached
            (
                "Test",
                typeof(String),
                typeof(MainWindow),
                new FrameworkPropertyMetadata
                    (
                        null,
                        FrameworkPropertyMetadataOptions.Inherits
                    )
            );
        public String Test
            {
                get { return (String)GetValue(TestProperty); }
                set { SetValue(TestProperty, value); }
            }
        public MainWindow()
        {
            InitializeComponent();
            Test = "Yip!";
        }
    }
}

UserControl1.xaml:

<UserControl x:Class="WpfApplication1.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" Name="BobControl">
    <Grid>
        <Label Content="UserControl1" />
        <TextBox Height="23" HorizontalAlignment="Left" Margin="85,2,0,0" Name="textBox1" VerticalAlignment="Top" Width="120" Text="{Binding Path=Test, ElementName=BobControl}" />
    </Grid>
</UserControl>

UserControl1.xaml.cs:

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

namespace WpfApplication1
{
    public partial class UserControl1 : UserControl
    {
        public static readonly DependencyProperty TestProperty = DependencyProperty.RegisterAttached
            (
                "Test",
                typeof(String),
                typeof(UserControl1),
                new FrameworkPropertyMetadata
                    (
                        null,
                        FrameworkPropertyMetadataOptions.Inherits
                    )
            );
        public String Test
            {
                get { return (String)GetValue(TestProperty); }
                set { SetValue(TestProperty, value); }
            }

        public UserControl1()
        {
            InitializeComponent();
        }
    }
}

これを達成するための明示的な例を見つけることができませんでした。MainWindow と UserControl1 での RegisterAttached の使用は、私の最善の推測です。私が見逃しているものがあるに違いない!

アップデート

任意の構造でコントロールを作成し、ツリーの一番上に値を設定し、デフォルト値を徐々に下げていきたいです (DataContext の動作と同様)。TestProperty が MainWindow と UserControl1 の共通の祖先クラスにない場合、これは可能ですか?

また、ソース クラスの参照は避けたいと思います。これは、ウィンドウになる場合もあれば、Windows フォームのホスト コントロールになる場合もあるためです。これは可能ですか?

解決

私の混乱は、アタッチされていない依存関係プロパティの構文を使用して値の継承を実現したかったことに起因していると思います。次のxamlを使用したかった:

<Window ... Test="Fred" />

次の構文を使用して、UserControl の継承された値にアクセスします。

string Value = this.Test;

ただし、Microsoft のプロパティ値の継承ページによると、プロパティ値を継承する場合は、添付プロパティを使用する必要があります。

上記のコードが適切に書き直された場合 (静的 getter/setter メソッドを使用してプロパティを 1 回宣言する)、私の xaml は次のようになります。

<Window ... my:MainWindow.Test="Fred" />

そして、UserControl のコード ビハインドは次のようになります。

string Value = MainWindow.GetTest( this );
4

2 に答える 2

2

値の継承の意味を誤解しているようです。コントロールに依存関係プロパティを設定すると、そのプロパティの値はその中のコントロールで同じになります。プロパティ自体を再宣言する必要はありません (完全に異なる別のプロパティを作成するだけです)。

継承の例:

<Window ...
        xmlns:local="..."
        local:MainWindow.Test="Lorem Ipsum">
    <Button Name="button"/>

コードでは、ボタンの値を取得できる必要があり、ウィンドウと同じである必要があります。

var test = (string)button.GetValue(MainWindow.TestProperty);
// test should be "Lorem Ipsum".
于 2012-04-10T14:29:56.280 に答える
1

ここで犯した間違いは、プロパティを 2 回宣言したことです。UserControl1 ではなく、MainWindow で宣言するだけです。次に、MainWindow で次のように静的 getter および setter メソッドを宣言します。

public static string GetTest(DependencyObject obj)
{
    return (String)obj.GetValue(TestProperty);       
}

public static void SetTest(DependencyObject obj, string value)
{
    obj.SetValue(TestProperty, value);
}

カスタム添付プロパティの詳細については、こちらをご覧ください。

UserControl1 が MainWindow の要素ツリーのどこかにある場合は、初期化後に UserControl1 で次のようなことを試してください。

UserControl1 uc = this; // for example in a UserControl1 event handler
string test = MainWindow.GetTest(uc);

編集: UserControl1 または他のクラスでプロパティを定義することもできます。これは添付プロパティであるため、そのクラスは DependencyObject から派生する必要さえありません。

于 2012-04-10T14:28:45.467 に答える