C# XamlWriter.Save会丢失列表框中的ItemsSource绑定
我有一个自定义的ContentControlC# XamlWriter.Save会丢失列表框中的ItemsSource绑定,c#,.net,wpf,C#,.net,Wpf,我有一个自定义的ContentControl public class DataControl : ContentControl { public List<DataItem> Options { get { return (List<DataItem>)GetValue(OptionsProperty); } set { SetValue(OptionsProperty, value); } } publ
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; }
}
有没有办法确保ItemsSource绑定被正确序列化,或者轻松地将其添加回去
当试图从另一个项目的ResourceDictionary中获取样式时,也会发生这种情况,例如
ResourceDictionary styles = new ResourceDictionary();
styles.Source = new Uri(String.Format("pack://application:,,,/StyleCopyTest;component/Styles/{0}Styles.xaml", type));
return styles;
在WPF源代码中,ItemsSource定义为
[Bindable(true), CustomCategory("Content"), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public IEnumerable ItemsSource { get; set; }
因此,XamlWriter无法序列化此文件
因此,您必须编写自己的序列化程序或使用前面提到的方法我找到了这个类,它可以帮助您序列化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;
}
}
}
这里是结果Xaml,包括ItemsSource绑定:
<ComboBox Width="100" Height="20" ItemsSource="{Binding Path=Model.Activity}" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" />
希望这有帮助,我仍然需要花一些时间来理解它,但到目前为止似乎正在工作…您是否尝试了中的解决方案?我尝试了,但它没有解决问题。.Net 4.0解决方案没有保留ItemsSource绑定,更糟糕的是,它会丢失ListBox.ItemTemplate中标签上的内容绑定。创建ExpressionConverter会修复内容绑定,但仍不会保存ItemsSource绑定。
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;
}
}
}
EditorHelper.Register<BindingExpression, BindingConvertor>();
ItemsControlTypeDescriptionProvider.Register();
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);
<ComboBox Width="100" Height="20" ItemsSource="{Binding Path=Model.Activity}" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" />