【问题标题】:CheckBox rendered as a LabelCheckBox 呈现为标签
【发布时间】:2016-08-20 09:06:36
【问题描述】:

我有一个动态生成的 ListView,它使用数据绑定来允许通过 CheckBox 编辑一些 Boolean 值。我使用 IValueConverter 生成 ListView 的列(如this 答案):

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 数据绑定到其他地方的某个其他值。但是,我得到的只是用文本代替复选框的列。文本正确,因此数据绑定有效,但 FrameworkElementFactory 对象未按预期工作。

为什么将复选框呈现/转换为文本框?

【问题讨论】:

  • 这是一种非常糟糕的做法。改用 MVVM 和数据模板
  • @Glen Thomas 我已经在使用 MVVM。我认为没有办法使用 DataTemplates 正确地做到这一点,是吗? DataTemplate 将适用于所有单元格,包括纯文本的第一列。
  • 您是否觉得自己正在掉进兔子洞?因为你要掉进兔子洞了。创建一个自定义控件或用户控件,它根据绑定对象的状态在代码隐藏中操纵 UI。
  • @Will 在尝试了该解决方案之后,如果不执行上述大部分操作,我仍然看不到您将如何做到这一点 - 唯一的变化是我在代码隐藏中而不是在转换器...

标签: c# wpf listview checkbox mvvm


【解决方案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,然后使用解析器对其进行解析。

由于文本合成是一项微不足道的任务,您可以在创建函数中传递任何参数(如我上面的示例所示)。

最后一点:这种方法很有用,但由于运行时解析和编译需要计算工作量。避免以这种方式创建大量项目。

【讨论】:

  • 嗯,这是一个问题(该表将有大约 100 个元素,并且会有一些表使用这个系统)。我想我会听从@Will 的建议,不要再往兔子洞深处走下去了。我将在后面的代码中做一个处理这个的 UserControl。
  • 100 个元素根本不是问题。我将这种方法用于具有数百个单元格的超级专业网格(对我来说这是一个“元素”),大部分都有一个相当复杂的 UI。我的意思是你应该避免对数千个单元使用这种方法。
  • 不,这是不必要的,因为上面的函数会生成一个直接注入到 ContentControl 的 DataTemplate 实例。当然,您可以预先计算(即编译)模板,而应用程序面临一个定义明确的布局。在我的情况下,它不是。但是,请尝试使用测试程序,以了解如何执行此方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-10-14
  • 2014-03-14
  • 2012-07-19
  • 2012-05-08
  • 1970-01-01
  • 2013-10-06
  • 1970-01-01
相关资源
最近更新 更多