2012-01-25 18 views
3

我有一個自ContentControl中XamlWriter.Save失去的ItemsSource從一個ListBox

public class DataControl : ContentControl 
{ 
    public List<DataItem> Options 
    { 
     get { return (List<DataItem>)GetValue(OptionsProperty); } 
     set { SetValue(OptionsProperty, value); } 
    } 

    public static readonly DependencyProperty OptionsProperty = 
     DependencyProperty.Register("Options", typeof(List<DataItem>), typeof(DataControl)); 

    public DataControl() 
    { 
     Options = new List<DataItem>(); 
    } 

    public string Label 
    { 
     get { return (string)GetValue(LabelProperty); } 
     set { SetValue(LabelProperty, value); } 
    } 

    // Using a DependencyProperty as the backing store for Label. This enables animation, styling, binding, etc... 
    public static readonly DependencyProperty LabelProperty = 
     DependencyProperty.Register("Label", typeof(string), typeof(DataControl)); 
} 

public class DataItem 
{ 
    public DataItem(string key, string value) 
    { 
     Key = key; 
     Value = value; 
    } 

    public string Key { get; set; } 

    public string Value { get; set; } 
} 

,其模板由下面的樣式應用結合:

<Style TargetType="{x:Type local:DataControl}" x:Key="DefaultStyle"> 
    <Setter Property="Template"> 
     <Setter.Value> 
      <ControlTemplate TargetType="{x:Type local:DataControl}"> 
       <StackPanel> 
       <ListBox ItemsSource="{TemplateBinding Options}" > 
        <ListBox.ItemTemplate> 
         <DataTemplate> 
         <Label Content="{Binding Key}" /> 
         </DataTemplate> 
        </ListBox.ItemTemplate> 
       </ListBox> 
       <Label Content="{TemplateBinding Label}" /> 
       </StackPanel> 
      </ControlTemplate> 
     </Setter.Value> 
    </Setter> 
</Style> 

如果我使用的XamlWriter保存這種風格和然後再讀回來,ItemsSource綁定會丟失,但標籤上的Content綁定不是。

Style style = Application.Current.TryFindResource("DefaultStyle") as Style; 

string s = XamlWriter.Save(style); 
Style secondStyle = XamlReader.Parse(s) as Style; 

有沒有一種方法來確保ItemsSource綁定序列化正確或將其輕鬆添加回來?

當嘗試從另一個項目的ResourceDictionary中獲取樣式時,也會發生這種情況,例如,

ResourceDictionary styles = new ResourceDictionary(); 
styles.Source = new Uri(String.Format("pack://application:,,,/StyleCopyTest;component/Styles/{0}Styles.xaml", type)); 
return styles; 
+0

您是否嘗試過[http://stackoverflow.com/questions/32541/how-can-you-clone-a-wpf-object](http://stackoverflow.com/questions/32541/如何可任意你克隆-A-WPF對象)? –

+0

我有,它不能解決問題。 .Net 4.0解決方案不保留ItemsSource綁定,而更糟糕的是會丟失ListBox.ItemTemplate中Label上的Content綁定。創建ExpressionConverter修復了內容綁定,但仍不保存ItemsSource綁定。 –

回答

2

在WPF源代碼中的ItemsSource被定義爲

[Bindable(true), CustomCategory("Content"),  DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] 
public IEnumerable ItemsSource { get; set; } 

因此,這不能由的XamlWriter被序列化。

所以你必須編寫自己的串行或使用方法中提到here

0

,我發現這個類here in code project,可幫助您序列化的ItemsControl屬性綁定:

using System; 
using System.Linq; 
using System.ComponentModel; 

namespace GUIKonfigurator 
{ 
    using System.Windows.Controls; 

    public class ItemsControlTypeDescriptionProvider:TypeDescriptionProvider 
    { 
     private static readonly TypeDescriptionProvider defaultTypeProvider = TypeDescriptor.GetProvider(typeof(ItemsControl)); 

     public ItemsControlTypeDescriptionProvider(): base(defaultTypeProvider) 
     { 
     } 

     public static void Register() 
     { 
      TypeDescriptor.AddProvider(new ItemsControlTypeDescriptionProvider(), typeof(ItemsControl)); 
     } 

     public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType,object instance) 
     { 
      ICustomTypeDescriptor defaultDescriptor = base.GetTypeDescriptor(objectType, instance); 
      return instance == null ? defaultDescriptor: new ItemsControlCustomTypeDescriptor(defaultDescriptor); 
     } 
    } 

    internal class ItemsControlCustomTypeDescriptor: CustomTypeDescriptor 
    { 
     public ItemsControlCustomTypeDescriptor(ICustomTypeDescriptor parent): base(parent) 
     { 
     } 

     public override PropertyDescriptorCollection GetProperties() 
     { 
      PropertyDescriptorCollection pdc = new PropertyDescriptorCollection(base.GetProperties().Cast<PropertyDescriptor>().ToArray()); 
      return ConvertPropertys(pdc); 
     } 

     public override PropertyDescriptorCollection GetProperties(Attribute[] attributes) 
     { 
      PropertyDescriptorCollection pdc = new PropertyDescriptorCollection(base.GetProperties(attributes).Cast<PropertyDescriptor>().ToArray()); 
      return ConvertPropertys(pdc); 
     } 

     private PropertyDescriptorCollection ConvertPropertys(PropertyDescriptorCollection pdc) 
     { 
      PropertyDescriptor pd = pdc.Find("ItemsSource", false); 
      if (pd != null) 
      { 
       PropertyDescriptor pdNew = TypeDescriptor.CreateProperty(typeof(ItemsControl), pd, new Attribute[] 
                             { 
                              new DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible), 
                              new DefaultValueAttribute("") 
                             }); 
       pdc.Add(pdNew); 
       pdc.Remove(pd); 
      } 
      return pdc; 
     } 
    } 
} 

你只需要註冊它像這在註冊BindingConvertor後:

EditorHelper.Register<BindingExpression, BindingConvertor>(); 
ItemsControlTypeDescriptionProvider.Register(); 

這裏我做了一個快速測試,創建一個ComboBox和其序列:

ComboBox cb = new ComboBox(); 
cb.Width = 100; 
cb.Height = 20; 
Binding b = new Binding("Model.Activity"); 
b.Source = this.DataContext; 
cb.SetBinding(ComboBox.ItemsSourceProperty, b); 
string xaml = _Serializer.SerializeControlToXaml(cb); 

這裏所產生的XAML中包括的ItemsSource綁定:

<ComboBox Width="100" Height="20" ItemsSource="{Binding Path=Model.Activity}" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" /> 

希望這有助於我還需要花一些時間來了解它,但到目前爲止似乎是工作.. 。

相關問題