【问题标题】:How to generate ListBox items dynamicaly based on type of value (bool/string/int)如何根据值类型(bool/string/int)动态生成 ListBox 项
【发布时间】:2017-10-11 12:13:33
【问题描述】:

我有一个项目: 原样:我正在基于 DataTemplate 生成 ListBox,其中包含来自 ObservableCollection 的数据(使用属性绑定) - 这很好用。它只包含带有名称的 texdtBlock 和带有值的 TextBox(双向绑定)。

待定:我想根据值的类型为值生成动态类型的字段。值可以是字符串 - 文本框、整数 - 文本框(理想情况是检查用户是否仅使用数字)、双精度和布尔值 - 复选框。

这是我的 XAML:

<ListBox x:Name="ListBox1">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="100"/>
                            <ColumnDefinition Width="200"/>
                        </Grid.ColumnDefinitions>
                        <TextBlock Text="{Binding Name}" Margin="2" Grid.Column="0"/>
                        <TextBox Text="{Binding Value, Mode=TwoWay}" Margin="2" Grid.Column="1" IsEnabled="{Binding IsLocked}"/>
                    </Grid>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>

这里是 C# 代码:

    InitializeComponent();
    DataContext = this;
    ListBox1.ItemsSource = valuesList;

虽然 valuesList 包含的对象具有: 字符串名称; 字符串值; (必须解析) 字符串类型; (稍后枚举)

您能给我一些关于如何生成这种 XAML 的提示吗?我的意思是可以使用绑定来做到这一点,还是我应该在后面的代码中创建“ListBoxRow”或其他东西并用它填充列表框?我想要一个更清洁的解决方案。那样的话,我认为我不会使用绑定,并且可能需要大量代码来完成它。

提前致谢。

【问题讨论】:

  • 所以你想绑定你的列表框并让每一行都有自定义控件,具体取决于“valuesList”中当前的类型?
  • 是的,完全正确。 As Name John 年龄 45 HasCar 复选框

标签: c# wpf xaml listbox


【解决方案1】:

有很多解决方案,但这应该是最简单的方法 - 如果它满足您的需求。

数据模板选择器

DataTemplateSelector 决定使用什么 DataTemplates 取决于您覆盖的逻辑。

public class MySampleClass
{
    public string Name;

    public object Value;
}


public class MyTemplateSelector : DataTemplateSelector
{

    public DataTemplate BooleanTemplate
    {
        get;
        set;
    }

    public DataTemplate DoubleTemplate
    {
        get;
        set;
    }

    public DataTemplate StringTemplate
    {
        get;
        set;
    }

    public override DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        MySampleClass temp = item as MySampleClass;


        if(temp.Value is bool)
        {
            return BooleanTemplate;
        }
        else if(temp.Value is double)
        {
            return DoubleTemplate;
        }
        else if(temp.Value is string)
        {
            return StringTemplate;
        }
        else
        {
            return base.SelectTemplate(item, container);

        }

        // And so on

    }
}

这是 - 如何使用它

<DataTemplate x:Key="StringTemplate">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="100"/>
            <ColumnDefinition Width="200"/>
        </Grid.ColumnDefinitions>
        <TextBlock Text="{Binding Name}" Margin="2" Grid.Column="0"/>
        <TextBox Text="{Binding Value, Mode=TwoWay}" Margin="2" Grid.Column="1" IsEnabled="{Binding IsLocked}"/>
    </Grid>
</DataTemplate>

<DataTemplate x:Key="BooleanTemplate">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="100"/>
            <ColumnDefinition Width="200"/>
        </Grid.ColumnDefinitions>
        <TextBlock Text="{Binding Name}" Margin="2" Grid.Column="0"/>
        <ToggleButton IsChecked="{Binding Value, Mode=TwoWay}" Margin="2" Grid.Column="1" IsEnabled="{Binding IsLocked}"/>
    </Grid>
</DataTemplate>

<selector:MyTemplateSelector BooleanTemplate="{StaticResource BooleanTemplate}"
                             StringTemplate="{StaticResource StringTemplate}"
                             x:Key="MyTemplateSelector"
                             />

<ListBox ItemTemplateSelector="{StaticResource MyTemplateSelector}" />

这是没有使用Resources

                <ListBox>
                    <ListBox.ItemTemplateSelector>
                        <selector:MyTemplateSelector>
                            <selector:MyTemplateSelector.StringTemplate>
                                <DataTemplate>
                                    <Grid>
                                        <Grid.ColumnDefinitions>
                                            <ColumnDefinition Width="100"/>
                                            <ColumnDefinition Width="200"/>
                                        </Grid.ColumnDefinitions>
                                        <TextBlock Text="{Binding Name}" Margin="2" Grid.Column="0"/>
                                        <TextBox Text="{Binding Value, Mode=TwoWay}" Margin="2" Grid.Column="1" IsEnabled="{Binding IsLocked}"/>
                                    </Grid>
                                </DataTemplate>
                            </selector:MyTemplateSelector.StringTemplate>
                            <selector:MyTemplateSelector.BooleanTemplate>
                                <DataTemplate>
                                    <Grid>
                                        <Grid.ColumnDefinitions>
                                            <ColumnDefinition Width="100"/>
                                            <ColumnDefinition Width="200"/>
                                        </Grid.ColumnDefinitions>
                                        <TextBlock Text="{Binding Name}" Margin="2" Grid.Column="0"/>
                                        <ToggleButton IsChecked="{Binding Value, Mode=TwoWay}" Margin="2" Grid.Column="1" IsEnabled="{Binding IsLocked}"/>
                                    </Grid>
                                </DataTemplate>
                            </selector:MyTemplateSelector.BooleanTemplate>
                        </selector:MyTemplateSelector>

                    </ListBox.ItemTemplateSelector>
                </ListBox>

请考虑selector 是一个已定义的命名空间,它取决于您解决方案中的项目。比如xmlns:selector="clr-namespace:MyApp.MyFolder.Selector"!!!

【讨论】:

  • 谢谢,这对我来说看起来不错。我正在尝试在我的代码中使用您的示例,但几乎没有错误。我忘了说,我正在使用 WPF。这是在 WPF 中吗?因为 1. 我不知道把这些数据模板放在哪里——visualstudio 不喜欢它,而且它也不知道选择器。似乎列表框只接受一个数据模板。并且 x:Key 不允许用于数据模板,只有 x:Name ...也许我现在看起来很愚蠢,因为我看不到的东西,但进一步的建议将不胜感激。
  • 这个XAML 队友。我将更改示例以使其更易于处理。
猜你喜欢
  • 2021-10-18
  • 1970-01-01
  • 1970-01-01
  • 2011-03-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-07
  • 1970-01-01
相关资源
最近更新 更多