2016-03-30 7 views
0

VS 2013とWPFでWPFウィンドウデザイナーアプリケーションをプログラミングしようとしています。 このアプリケーションでは、コントロールが作成され、実行時にCanvasに配置されます。プロパティとバインディングの設定を含む このような動的WPFウィンドウの完成後、Canvasを直列化し、その子コントロールをXMLファイルにシリアル化します。このため は、我々はそのようなXamlWriterを使用している:コードビハインドで生成されたコントロールのバインディングがXamlWriterによってシリアル化されていません

public string SerializeControlToXaml(FrameworkElement control) 
{ 
    StringBuilder outstr = new StringBuilder(); 

    XmlWriterSettings settings = new XmlWriterSettings(); 
    settings.Indent = true; 
    settings.OmitXmlDeclaration = true; 
    XamlDesignerSerializationManager dsm = 
     new XamlDesignerSerializationManager(XmlWriter.Create(outstr, settings)); 
    dsm.XamlWriterMode = XamlWriterMode.Expression; 
    System.Windows.Markup.XamlWriter.Save(control, dsm); 

    string xaml = outstr.ToString(); 
    return xaml; 
} 

「コントロール」パラメータは、我々の場合には、すべてのコードビハインド作成したコントロールの親コントロールであるキャンバスパネルが含まれています。 とりわけ、SelectedItemとDataGridの列にバインドされたTextBoxesを作成しています。

private void CreateTextboxes() 
{ 
    CreateTextbox("firstname", _datagridname, "SelectedItem.vorname", 220, 10); 
    CreateTextbox("familyname", _datagridname, "SelectedItem.nachname", 220, 40); 
} 

private void CreateTextbox(string name, string sourceName, string path, double leftPos, double topPos) 
{ 
    TextBox tb = new TextBox(); 
    tb.SetValue(Canvas.LeftProperty, leftPos); 
    tb.SetValue(Canvas.TopProperty, topPos); 
    tb.Width = 150; 
    tb.Name = name; 

    // Binding to the selected item of the DataGrid. 
    Binding tbbinding = new Binding(); 
    FrameworkElement sourceElement; 
    ControlList.TryGetValue(sourceName, out sourceElement); 
    if (sourceElement != null) 
    { 
     tbbinding.Source = sourceElement; 
    } 
    tbbinding.Path = new PropertyPath(path); 
    tb.SetBinding(TextBox.TextProperty, tbbinding); 

    _canvasPanel.Children.Add(tb); 

    // The new TextBox is added to the Controllist. 
    ControlList.Add(name, tb); 
} 

この例では、TextBoxを作成し、そのプロパティとバインディングを設定する方法が2回呼び出されています。 最後に、ウィンドウに「firstname」と「familyname」のDataGrid列にバインドされた2つのテキストボックスがあります。

親コントロールをシリアル化するとき、バインドはシリアル化されません。私たちは何を得る は以下のようになります。

<Canvas Background="#FFF0F8FF" Name="DropInCanvas" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:sd="clr-namespace:System.Data;assembly=System.Data" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> 
    <DataGrid CanUserAddRows="False" AutoGenerateColumns="True" Name="datagrid1" Canvas.Left="20" Canvas.Top="10"> 
    <DataGrid.ItemBindingGroup> 
     <BindingGroup Name="{x:Null}" NotifyOnValidationError="False" ValidatesOnNotifyDataError="True" SharesProposedValues="True" /> 
    </DataGrid.ItemBindingGroup> 
    <sd:DataRowView /> 
    <sd:DataRowView /> 
    <sd:DataRowView /> 
    <sd:DataRowView /> 
    </DataGrid> 
    <TextBox Name="firstname" Width="150" Canvas.Left="220" Canvas.Top="10" xml:space="preserve"></TextBox> 
    <TextBox Name="familyname" Width="150" Canvas.Left="220" Canvas.Top="40" xml:space="preserve"></TextBox> 
</Canvas> 

誰もがなぜ知っていますか?

ありがとうございます!

我々は、コンバータのクラスが必要BindingExpressionsをシリアライズするパトリック

答えて

0

/// <summary> 
/// Class for conversion of binding-attributes while XML-serialization. 
/// With this converter it is possible to serialize the control-bindings. 
/// Works together with the class EditorHelper. 
/// </summary> 
public class BindingConvertor : ExpressionConverter 
{ 
    /// <summary> 
    /// Finds out if the converter can convert an expression-object to the given destinationtype. 
    /// </summary> 
    /// <param name="context">An ITypeDescriptorContext-interface which provides a context for formatting.</param> 
    /// <param name="destinationType">A type-class which represents the target-type of the conversion.</param> 
    /// <returns>Returns an object of type bool. True = the destinationtype can be converted.</returns> 
    public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) 
    { 
     if (destinationType == typeof(MarkupExtension)) 
      return true; 

     return false; 
    } 

    /// <summary> 
    /// Converts the expression to the given destinationtype. 
    /// </summary> 
    /// <param name="context">An ITypeDescriptorContext-interface which provides a context for formatting.</param> 
    /// <param name="culture">The System.Globalization.CultureInfo which is actually used as culture.</param> 
    /// <param name="value">The object to convert.</param> 
    /// <param name="destinationType">A type-class which represents the target-type of the conversion.</param> 
    /// <returns></returns> 
    public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, 
     Type destinationType) 
    { 
     if (destinationType == typeof(MarkupExtension)) 
     { 
      BindingExpression bindingExpression = value as BindingExpression; 
      if (bindingExpression == null) 
       throw new Exception(); 
      return bindingExpression.ParentBinding; 
     } 

     return base.ConvertTo(context, culture, value, destinationType); 
    } 
} 

次は私達が表現のどのタイプを担当するコンバータ登録するエディタが必要:

/// <summary> 
/// Class for registering the class BindingConvertor as the type-converter for the type BindingExpression 
/// With this converter it is possible to serialize the control-bindings. 
/// </summary> 
public class EditorHelper 
{ 
    /// <summary> 
    /// Registers which converter is responsible for which type. 
    /// </summary> 
    /// <typeparam name="T">The type.</typeparam> 
    /// <typeparam name="TC">The converter.</typeparam> 
    public static void Register<T, TC>() 
    { 
     Attribute[] attribute = new Attribute[1]; 
     TypeConverterAttribute typeConverterAttribute = new TypeConverterAttribute(typeof(TC)); 
     attribute[0] = typeConverterAttribute; 
     TypeDescriptor.AddAttributes(typeof(T), attribute); 
    } 
} 

がそれを完了するために、私たちは、どこかのコードに次のコード行を実装する必要があり、当社MainWindow(または必要な場所):

EditorHelper.Register<BindingExpression, BindingConvertor>(); 

これだけです!

関連する問題