2

私は、標準の XamlWriter がバインドを保持しないことを知っています。しかし、本当に厄介なのは、バインディングが保持する現在の値もシリアル化されないことです。

私の現在の - 本当にばかげた - 回避策は、DependencyProperty fooProperty とプロパティ foo を作成することです。また、プロパティ foo2 もあります。次に、foo の Change-eventhandler がその値を foo2 に書き込みます。

あなたが見る:ばか。

誰かがより良い解決策を持っていますか?

乾杯

-- トーマスに応じて編集 --

基本的にあなたは正しいです。ただし、ItemsControl を使用する場合は少し異なります。

<Window x:Class="TestApp.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:TestApp"
    Title="MainWindow" Height="350" Width="525"
    x:Name="window"
    >
<StackPanel>
    <StackPanel.Resources>
        <x:Array x:Key="arr1" Type="{x:Type local:TestData}">
            <local:TestData Message="itemcontrol binding 1"/>
            <local:TestData Message="itemcontrol binding 2"/>
        </x:Array>
   </StackPanel.Resources>

    <local:Test Foo="hard coded"/>
    <local:Test Foo="{Binding Message, ElementName=window}"/>
    <ItemsControl ItemsSource="{StaticResource arr1}">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <local:Test Foo="{Binding Path=Message }"/>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
</StackPanel>

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        Message = "direct binding";
    }

    public static DependencyProperty MessageProperty = DependencyProperty.Register("Message", typeof(string), typeof(MainWindow));
    public string Message
    {
        get { return (string)GetValue(MessageProperty); }
        set { SetValue(MessageProperty, value); }
    }
}

public class Test : TextBox
{
    public static DependencyProperty FooProperty = DependencyProperty.Register("Foo", typeof(string), typeof(Test), new PropertyMetadata(OnFooChanged));
    private static void OnFooChanged(DependencyObject d, DependencyPropertyChangedEventArgs a)
    {
        (d as Test).Text = a.NewValue as String;
    }
    public string Foo
    {
        get { return (string)GetValue(FooProperty); }
        set { SetValue(FooProperty, value); }
    }

    protected override void OnMouseEnter(MouseEventArgs e)
    {
        Debug.Print("foo is really: " + Foo);
        Debug.Print(XamlWriter.Save(this));
    }
}

public class TestData : DependencyObject
{
    public static DependencyProperty MessageProperty = DependencyProperty.Register("Message", typeof(string), typeof(TestData));
    public string Message
    {
        get { return (string)GetValue(MessageProperty); }
        set { SetValue(MessageProperty, value); }
    }
}

このテスト アプリケーションを実行し、カーソルを別の TextBox の上に移動すると、ハード コードされた値と直接バインドされた値のシリアル化に問題がないことがわかります。逆に、データ テンプレート バインディングはシリアル化されません。

ちなみに、StaticReference の代わりにコードによって生成された ItemsSource を使用することに違いはありません。

4

2 に答える 2

0

ItemTemplate 内のバインディングの同じケースで、同じことを見てきました。

<ListBox.ItemTemplate>
    <DataTemplate>
        <TextBlock Text="{Binding}"/>
    </DataTemplate>
</ListBox.ItemTemplate>

私ができる最善の方法は、次の回避策です。

private static UIElement ClonedElement(UIElement original)
{
    var clone = (UIElement)XamlReader.Parse(XamlWriter.Save(original));

    if (original is TextBlock)
        //Handles situation where databinding doesn't clone correctly.
        ((TextBlock)clone).Text = ((TextBlock)original).Text;
    return clone;
}

きれいではありませんが、機能します。(そして、あなたが失っているどんなプロパティでも簡単に変更できます。)

于 2012-02-15T21:50:30.350 に答える
0

によって保持されXamlWriterます。このページを参照してください:

XamlWriter.Save のシリアル化の制限事項

StaticResource や Binding など、さまざまなマークアップ拡張フォーマットによって作成されたオブジェクトへの一般的な参照は、シリアル化プロセスによって逆参照されます。これらは、メモリ内オブジェクトがアプリケーション ランタイムによって作成された時点で既に逆参照されており、保存ロジックは、シリアル化された出力へのそのような参照を復元するために元の XAML を再訪しません。これにより、データバインドされた値またはリソースで取得された値が、ランタイム表現によって最後に使用された値になる可能性があります。、そのような値をローカルに設定された他の値と区別する能力が限定的または間接的にしかありません。また、イメージは、元のソース参照としてではなく、プロジェクトに存在するイメージへのオブジェクト参照としてシリアル化され、最初に参照されていたファイル名または URI が失われます。同じページ内で宣言されたリソースでさえ、リソース コレクションのキーとして保持されるのではなく、参照された時点でシリアル化されて表示されます。

簡単なテストを行ったところ、問題なく動作します。

public class Test : DependencyObject
{
    public static DependencyProperty FooProperty = DependencyProperty.Register("Foo", typeof(string), typeof(Test));

    public string Foo
    {
        get { return (string)GetValue(FooProperty); }
        set { SetValue(FooProperty, value); }
    }

    public static DependencyProperty BarProperty = DependencyProperty.Register("Bar", typeof(int), typeof(Test));

    public int Bar
    {
        get { return (int)GetValue(BarProperty); }
        set { SetValue(BarProperty, value); }
    }
}

public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {
        base.OnStartup(e);

        Message = "Hello";
        Answer = 42;

        var t = new Test();

        Binding fooBinding = new Binding("Message") { Source = App.Current };
        BindingOperations.SetBinding(t, Test.FooProperty, fooBinding);

        Binding barBinding = new Binding("Answer") { Source = App.Current };
        BindingOperations.SetBinding(t, Test.BarProperty, barBinding);

        var s = XamlWriter.Save(t);
        Debug.Print(s);

    }

    public string Message { get; set; }
    public int Answer { get; set; }
}

このプログラムは、デバッグ出力に次の XAML を出力します。

<Test Foo="Hello" Bar="42" xmlns="clr-namespace:WpfApplication1;assembly=WpfApplication1" />

したがって、あなたのケースで機能しない別の理由があるに違いありません...バインディングエラーがありませんか? シリアル化する前に、オブジェクトに期待される値がありますか?

于 2010-07-13T07:48:06.053 に答える