2010-07-12 3 views
1

표준을 알고 XamlWriter 바인딩을 유지하지 않습니다. 하지만 실제로 악취가 나는 것은 바인딩이 보유하고있는 현재 값이 직렬화되지 않는다는 것입니다.XamlWriter 바인딩이 끊어졌습니다 - 확인! 그러나 가치를 지키는 방법? (ItemsControl)

내 현재 - 정말 바보 같은 - 해결 방법은 DependencyProperty fooProperty와 foo 속성을 만드는 것입니다. 또한 속성 foo2. foo의 Change-eventhandler는 그 값을 foo2에 기록합니다.

다음을 참조하십시오.

누구에게 더 좋은 해결책이 있습니까?

환호

- 편집 응답 토마스 -

은 기본적으로 당신 말이 맞아. 이 테스트 응용 프로그램을 실행하고 다른 텍스트 상자 위로 커서를 이동하면

<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); } 
    } 
} 

는, 당신이이 직렬화 문제를 프로그래머 없습니다 볼 수 있습니다하십시오 ItemsControl에를 사용하는 경우 그러나 그것은 다른 조금 보인다 하드 코드 된 및 바로 바인딩 된 값. 반대로 템플릿 템플릿 데이터가 직렬화되지 않습니다. 대신 StaticReference의 코드에 의해 생성 된 ItemsSource 사용에 아무런 차이가 없을 그런데

은 단지 테스트 ..

답변

0

XamlWriter 의해 유지되는 값. 이 페이지를 참조하십시오 : 같은 정적 리소스 또는 바인딩 등 다양한 마크 업 확장 형식에 의해 만들어진 객체에

Serialization Limitations of XamlWriter.Save

공통 참조를 직렬화 프로세스에 의해 역 참조됩니다. 이들은 응용 프로그램 런타임에서 메모리 내 객체를 만들 때 저장 참조 논리가 원래의 XAML을 다시 방문하지 않고 직렬화 된 출력에 대한 참조를 복원 할 때 이미 참조 해제되었습니다. 이것은 데이터 바인드 또는 자원 획득 값을 런타임시 표현에 의해 마지막으로 사용 된 값으로 동결시킬 수 있으며이 값을 국지적으로 설정된 다른 값과 구별하는 데 제한적이거나 간접적 인 기능 만 있습니다. 이미지는 또한 원래 소스 참조가 아닌 프로젝트에있는 이미지에 대한 객체 참조로 일련 번호가 지정되어 원래 참조 된 파일 이름이나 URI가 손실됩니다. 동일한 페이지 내에서 선언 된 리소스조차도 리소스 컬렉션의 키로 유지되기보다는 참조 된 시점으로 직렬화 된 것으로 간주됩니다.

난 그냥 간단한 테스트를했고, 나를 위해 잘 작동 :

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

그래서 서로가 있어야합니다 :

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을 인쇄 왜 귀하의 사건에서 작동하지 않는 이유는 ... 당신은 어떤 바인딩 오류가 없어 확신합니까? 개체를 serialize하기 전에 개체에 예상 값이 있습니까?

나는 ItemTemplate을 내부 결합의 동일한 경우, 같은 일을 보았다
+0

답장을 보내 주셔서 감사합니다. 당신이 옳은 것 같아요 .. 내 테스트 베드에서 아직이 버그를 재현 할 수 없습니다. 내 실제 응용 프로그램에는 ContentControls가 많이 있습니다. TabControl, ItemControl, ItemControl. 거기에 바인딩은 RelativeSource FindAncestor를 통해 작동합니다 .. 좀 더 살펴 보겠습니다. – kris

+0

보세요. :) – kris

0

:

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; 
} 

하는 것은 아 인 :

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

내가 할 수있는 최선은 다음과 같은 해결 방법입니다 예쁘지 만 작동합니다. (그리고 재산을 잃어 버리면 쉽게 수정할 수 있습니다.)