2016-04-26 7 views
2

У меня есть динамически сгенерированный ListView, который использует привязку данных для редактирования некоторых значений Boolean через CheckBox. Я использую IValueConverter для создания столбцов в ListView в (как в this ответ):CheckBox, отображаемый как метка

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

Который используется, как это в XAML:

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

заголовки столбцов, генерируются в другом месте. Код должен принимать значения ColumnConfig и создавать объекты GridViewColumn с привязкой к базе данных ChechBox для некоторых других целей в другом месте. Тем не менее, все, что я получаю, это столбцы с текстом вместо CheckBoxes. Текст верный, поэтому привязка данных действительна, но объект FrameworkElementFactory работает не так, как ожидалось.

Почему флажки отображаются/конвертируются в текстовые поля?

+0

Это действительно плохой способ сделать это. Вместо этого используйте MVVM и шаблоны данных –

+0

@Glen Thomas Я уже использую MVVM. Я не думаю, что есть способ сделать это правильно с DataTemplates, не так ли? DataTemplate применим ко всем ячейкам, включая первый столбец, который является текстовым. – MKII

+0

Вы чувствуете, что идете по кроличьей дыре? Потому что ты спускаешься в кроличью нору. Создайте настраиваемый элемент управления или пользовательский элемент управления, который управляет пользовательским интерфейсом в коде, основываясь на состоянии объектов, с которыми он связан. – Will

ответ

1

Правило: избегать этого способа динамически составлять шаблон.

У меня была аналогичная проблема, и я решил следующим образом:

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

В принципе, вы должны составить полностью действительный XAML вашего шаблона, а затем разобрать его с анализатором.

Поскольку текстовая композиция является тривиальной задачей, вы можете передать любой параметр в функции создания (как в моем примере выше).

Просто последнее замечание: этот подход полезен, но требует вычислительных усилий, поскольку анализ времени выполнения и компиляция выполняются. Избегайте большого количества элементов, созданных таким образом.

+0

Well , то есть проблема (таблица будет иметь ~ 100 элементов, и будет несколько таблиц, которые используют эту систему). Наверное, я буду следовать совету Уилла и перестать спускаться вниз по лунке кролика. Я просто сделаю UserControl, который справится с этим в коде. – MKII

+0

100 элементов не проблема. Я использую этот подход для суперспециализированной сетки, содержащей сотни ячеек (для меня это «элемент»), в основном имеют довольно сложный интерфейс. Я имею в виду, что вам следует избегать такого подхода для многих тысяч ячеек. –

+0

Нет, это необязательно, потому что вышеприведенная функция генерирует экземпляр DataTemplate, который вводится непосредственно в ContentControl. Конечно, вы можете предварительно вычислить (то есть скомпилировать) шаблоны, тогда как приложение сталкивается с четко определенным макетом. В моем случае это не так. Однако попробуйте с помощью тестовой программы, чтобы понять, как это сделать. –

Смежные вопросы