2016-04-26 13 views
2

Ich habe eine dynamisch generierte ListView, die Datenbindung verwendet, um einige Werte über CheckBox zu bearbeiten. Ich benutze eine IValueConverter zu den Spalten der Listview zu erzeugen (wie in this Antwort):CheckBox als ein Label gerendert

public object Convert (object Value, Type EntryType, object Parameter, System.Globalization.CultureInfo Culture) 
{ 
    var Config = Value as ColumnConfig; 
    if (Config != null) 
    { 
     var GridView = new GridView(); 
     Binding NameBinding = new Binding ("Name"); 
     GridViewColumn BaseColumn = new GridViewColumn { Header = "Settings", 
                 DisplayMemberBinding = NameBinding, 
                 Width = 125, 
                 CellTemplate = new DataTemplate()}; 
     GridView.Columns.Add (BaseColumn); 

     foreach (Column CurrentColumn in Config.Columns) 
     { 
      Binding NewBinding = new Binding (CurrentColumn.DataField); 
      FrameworkElementFactory FEF = new FrameworkElementFactory (typeof (CheckBox)); 
      FEF.SetBinding (CheckBox.IsCheckedProperty, NewBinding); 

      GridViewColumn GVColumn = new GridViewColumn 
              { 
               Header = CurrentColumn.Header, 
               DisplayMemberBinding = NewBinding 
              }; 
      var DTemplate = new DataTemplate(); 
      DTemplate.VisualTree = FEF; 

      GVColumn.CellTemplate = DTemplate; 

      GridView.Columns.Add (GVColumn); 
     } 

     return GridView; 
    } 

    return Binding.DoNothing; 
} 

, die wie so in der XAML verwendet wird:

<ListView Margin="2" ItemContainerStyle="{StaticResource LineHighlightListView}" 
       ItemsSource="{Binding InMatrixList}" 
       View="{Binding InMatrixColumns, Converter={StaticResource ConvertItemsToDynamicGridView}}" /> 

den Spalten Header werden an anderer Stelle erzeugt. Der Code sollte eine ColumnConfig Elemente aufnehmen und GridViewColumn Objekte erstellen, die eine ChechBox Datenverbindung zu einem anderen Wert an anderer Stelle haben. Alles, was ich bekomme, sind jedoch Spalten mit Text anstelle der CheckBoxen. Der Text ist korrekt, daher ist die Datenbindung gültig, aber das Objekt FrameworkElementFactory funktioniert nicht wie erwartet.

Warum werden die Kontrollkästchen in Textboxen gerendert/konvertiert?

+0

Dies ist eine wirklich schlechte Art, es zu tun. Verwenden Sie stattdessen MVVM und Datenvorlagen –

+0

@Glen Thomas Ich verwende bereits MVVM. Ich denke nicht, dass es eine Möglichkeit gibt, dies mit DataTemplates richtig zu machen, oder? Das DataTemplate würde für alle Zellen gelten, einschließlich der ersten Spalte, die nur Text enthält. – MKII

+0

Fühlst du dich wie ein Kaninchenloch? Weil du ein Kaninchenloch durchgehst. Erstellen Sie ein benutzerdefiniertes Steuerelement oder eine Benutzersteuerung, die die Benutzeroberfläche im Codebehind basierend auf dem Status der Objekte bearbeitet, an die sie gebunden ist. – Will

Antwort

1

Regel: vermeiden Sie diesen Weg, um dynamisch eine Vorlage zu komponieren.

Ich hatte ein ähnliches Problem, und ich gelöst haben, wie folgt: Grundsätzlich

//see: http://www.codeproject.com/Articles/444371/Creating-WPF-Data-Templates-in-Code-The-Right-Way 
    private static DataTemplate CreateTemplate(UniprogCellVM cell) 
    { 
     var tcell = cell.GetType(); 

     var sb = new StringBuilder(); 
     sb.AppendFormat("<DataTemplate DataType=\"{{x:Type local:{0}}}\">", tcell.Name); 
     sb.Append("<local:UniprogCellControl "); 
     sb.Append("Content=\"{Binding Path=.}\" "); 
     sb.Append("Header=\"{Binding Path=.}\" "); 
     sb.AppendFormat("Style=\"{{DynamicResource Root{0}BoxStyleKey}}\" ", cell.Interaction); 
     sb.Append(">"); 

     sb.Append("</local:UniprogCellControl>"); 
     sb.Append("</DataTemplate>"); 

     var context = new ParserContext(); 

     context.XamlTypeMapper = new XamlTypeMapper(new string[0]); 
     context.XamlTypeMapper.AddMappingProcessingInstruction("local", tcell.Namespace, tcell.Assembly.FullName); 

     context.XmlnsDictionary.Add("", "http://schemas.microsoft.com/winfx/2006/xaml/presentation"); 
     context.XmlnsDictionary.Add("x", "http://schemas.microsoft.com/winfx/2006/xaml"); 
     context.XmlnsDictionary.Add("local", "local"); 

     var template = (DataTemplate)XamlReader.Parse(sb.ToString(), context); 
     return template; 
    } 

Sie eine voll gültige XAML Ihrer Vorlage zusammensetzen sollte, dann analysieren sie mit dem Parser.

Da die Textkomposition eine triviale Aufgabe ist, können Sie einen beliebigen Parameter in der Erstellungsfunktion übergeben (wie in meinem Beispiel oben).

Nur eine letzte Anmerkung: Dieser Ansatz ist nützlich, erfordert aber einen Rechenaufwand wegen der Laufzeitanalyse und -kompilierung. Vermeiden Sie eine große Anzahl von Objekten, die auf diese Weise erstellt wurden.

+0

Nun , das ist ein Problem (die Tabelle würde ~ 100 Elemente haben, und es würde ein paar Tabellen geben, die dieses System benutzen). Ich schätze, ich werde @ Wills Ratschlag befolgen und aufhören, tiefer in das Kaninchenloch zu kommen. Ich werde einfach eine UserControl machen, die sich damit im Code beschäftigt. – MKII

+0

100 Elemente sind überhaupt kein Problem. Ich verwende diesen Ansatz für ein superspezialisiertes Grid mit Hunderten von Zellen (das ist ein "Element" für mich), habe meistens eine ziemlich komplexe Benutzeroberfläche. Ich meine, Sie sollten diesen Ansatz für viele tausend Zellen vermeiden. –

+0

Nein, das ist unnötig, weil die obige Funktion eine DataTemplate-Instanz erzeugt, die direkt in ein ContentControl injiziert wird. Natürlich könnten Sie die Vorlagen vorberechnen (d. H. Kompilieren), während die Anwendung einem klar definierten Layout gegenübersteht. In meinem Fall ist es nicht. Versuchen Sie es jedoch mit einem Testprogramm, nur um zu erkennen, wie dieser Ansatz durchgeführt wird. –