【问题标题】:How to display a control dynamically in wpf?如何在 wpf 中动态显示控件?
【发布时间】:2011-12-27 06:26:08
【问题描述】:

我有一个包含cityname、statename 和countryname 字段的集合,我将该集合绑定到我的wpf 表单。我想在文本框中显示城市名称,在组合框中显示州名,在组合框中显示国家名称。所有的文本框和组合框都应该是动态的。我该如何做这份工作?

有人建议我如何使用 MVVM 在 wpf 中动态设计此表单 我正在尝试执行此代码但无法正确获得结果

<UserControl.Resources>

<DataTemplate x:Key="IntegerTemplate">
    <DockPanel>
        <TextBox Margin="10,0,0,0" x:Name="IntegerTemplate" Grid.Column="1" MaxLength="{Binding Path=CardField.MaximumLength}" Text="{Binding Path=CardField.FieldData, Mode=TwoWay}" />
    </DockPanel>
</DataTemplate>

<DataTemplate x:Key="StringTemplate">
    <DockPanel>
        <ComboBox Margin="10,0,0,0" x:Name="cmbFieldData" Grid.Column="1" Text="{Binding Path=CardField.FieldData, Mode=TwoWay}" />
    </DockPanel>
</DataTemplate>
<DataTemplate x:Key="DefaultTemplate">
</DataTemplate>
<DataTemplate x:Key="dataTemplate">
    <ContentControl x:Name="MyContentControl"  Content="{Binding}" ContentTemplate="{StaticResource DefaultTemplate}"/>
        <DataTemplate.Triggers>
            <DataTrigger Binding="{Binding Path=CardField.FieldTag}" Value="City">
                <Setter TargetName="MyContentControl" Property="ContentTemplate"
                   Value="{StaticResource IntegerTemplate}" />
            </DataTrigger>
            <DataTrigger Binding="{Binding Path=CardField.FieldTag}" Value="State">
                <Setter TargetName="MyContentControl" Property="ContentTemplate"
                   Value="{StaticResource StringTemplate}" />
            </DataTrigger>
            <DataTrigger Binding="{Binding Path=CardField.FieldTag}" Value="Country">
                <Setter TargetName="MyContentControl" Property="ContentTemplate"
                   Value="{StaticResource StringTemplate}" />
            </DataTrigger>
            <!-- and so on -->
        </DataTemplate.Triggers>
    </DataTemplate>
</UserControl.Resources>

我们在我们的 xaml 页面中使用此代码

<ItemsControl x:Name="items"
 ItemsSource="{Binding}"
 ItemTemplate="{StaticResource dataTemplate}"
/>

更新: 我正在尝试执行以下代码:

<TextBlock x:Name="tbFieldTag" Cursor="Hand" VerticalAlignment="Center" HorizontalAlignment="Stretch" TextWrapping="Wrap" Margin="10,0,0,0" Text="{Binding Path=CardField.FieldTag}" />
            <ItemsControl x:Name="items"
ItemsSource="{Binding}"
ItemTemplate="{StaticResource dataTemplate}"/>

我得到了 TextBlock 的值,但我没有得到 ItemTemplate 中的值。那我哪里做错了?

【问题讨论】:

  • 您的方法对我来说似乎有效。什么不适合你?
  • 我没有在这段代码中获得动态控制
  • @ColinE:我在我的视图模型中使用 Vladimir Dorokhov 指定的“数据模板选择器”:在下面的答案中,但不幸的是,在调试期间没有调用该类。

标签: c# .net wpf mvvm wpf-controls


【解决方案1】:

试试这个:

1) 数据模板选择器

  public class CardFieldTemplateSelector : IValueConverter
    {

            public DataTemplate CityNameTemplate { get; set; } 

            public DataTemplate StateNameTemplate { get; set; }


            public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
            {
                string fieldTag = (string) value;
                switch (fieldTag)
                {
                    case "City":
                        return CityNameTemplate;
                    case "State":
                        return StateNameTemplate;
                }

                throw new ArgumentOutOfRangeException();
            }

            public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
            {
                throw new NotSupportedException();
            }
        }

2) XAML:

 <selectors:CardFieldTemplateSelector x:Key="cardFieldTemplateSelector">
   <selectors:CardFieldTemplateSelector.CityNameTemplate>
     <DataTemplate>
      <DockPanel>
        <TextBox Margin="10,0,0,0" x:Name="IntegerTemplate" Grid.Column="1" MaxLength="{Binding Path=CardField.MaximumLength}" Text="{Binding Path=CardField.FieldData, Mode=TwoWay}" />
      </DockPanel>
     </DataTemplate>
   </selectors:CardFieldTemplateSelector.CityNameTemplate>

   <selectors:CardFieldTemplateSelector.StateNameTemplate>
     <DataTemplate>
      <DockPanel>
        <ComboBox Margin="10,0,0,0" x:Name="cmbFieldData" Grid.Column="1" Text="{Binding Path=CardField.FieldData, Mode=TwoWay}" />
     </DockPanel>
     </DataTemplate>
   </selectors:CardFieldTemplateSelector.StateNameTemplate>
 </selectors:CardFieldTemplateSelector>

<DataTemplate x:Key="dataTemplate">
   <ContentControl x:Name="MyContentControl" 
                   Content="{Binding}"
                   ContentTemplate="{Binding CardField.FieldTag, Converter={StaticResource cardFieldTemplateSelector}"/>
</DataTemplate>

<ItemsControl x:Name="items"
 ItemsSource="{Binding}"
 ItemTemplate="{StaticResource dataTemplate}"/>

【讨论】:

  • CardFieldTemplateSelector 类文件在运行时不调用
  • 在运行时不调用数据模板选择器。我错过了对课程的引用吗?我应该指定更多代码以更好地理解问题吗?
  • 更新了代码。如果未调用数据模板选择器,请确保数据上下文正确,并且您已提供具有 CardField.FieldTag 路径的必要视图模型
  • 请检查我的更新部分,我已经更新了我正在尝试做的代码
  • 你应该在ItemsSource中绑定IEnumerable,在DataTemplate描述的每一项的DataContext中都会有T。在你的情况下 T 应该有 CardField.FieldTag。
【解决方案2】:

为什么不能使用来自Codeplex 的 WPF 数据表单。

您可以根据数据类型在此表单中添加自定义编辑器。

希望对您有所帮助。

【讨论】:

  • 没有合适的文档来使用它。我对 WPF 数据绑定很陌生。
猜你喜欢
  • 2020-12-31
  • 1970-01-01
  • 2017-11-19
  • 2021-06-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-10
  • 1970-01-01
相关资源
最近更新 更多