wpf - DataTemplate 绑定(bind)取决于属性类型和工作属性绑定(bind)

标签 wpf xaml mvvm binding datatemplate

我检查了那些关于做 DataTemplate 的文章:

  • WPF DataTemplate Binding
  • WPF DataTemplate and Binding
  • WPF DataTemplate Textblock binding

  • 以及关于 DataTemplate 的那些取决于属性类型:
  • WPF DataTemplate Binding depending on the type of a property
  • Dynamically display a control depending on bound property using WPF

  • 我正在尝试根据属性值显示具有不同控件的属性。我有这个部分工作的 Xaml。我有两个问题:
  • 该属性使用正确的控件显示,但是当我设置该值时,它不会返回到该属性。表示未调用我的属性的“集合”(但在我创建 DataTemplate 之前)。我检测到有关设置属性的问题是关于 ="{Binding Path=.}"但我找不到其他设置它的解决方案。
  • 此外,为了使其工作,我必须将值“隔离”到单个 ViewModel 中,以便 DataTemplate 不会影响所有其他控件。

  • 你能帮我找到更好的解决方案来解决这两个问题吗?

    这是我的 View 的 xaml 代码,它与具有“ChangingDataType”的 MyContainerViewModel 链接:
    <UserControl >
    <UserControl.Resources>
        <!-- DataTemplate for strings -->
        <DataTemplate DataType="{x:Type sys:String}">
            <TextBox Text="{Binding Path=.}" HorizontalAlignment="Stretch"/>
        </DataTemplate>
        <!-- DataTemplate for bool -->
        <DataTemplate DataType="{x:Type sys:Boolean}">
            <CheckBox IsChecked="{Binding Path=.}" />
        </DataTemplate>
        <!-- DataTemplate for Int32 -->
        <DataTemplate DataType="{x:Type sys:Int32}">
            <dxe:TextEdit Text="{Binding Path=.}" MinWidth="50" Mask="d" MaskType="Numeric" HorizontalAlignment="Stretch"/>
            <!--<Slider Maximum="100" Minimum="0" Value="{Binding Path=.}" Width="100" />-->
        </DataTemplate>
        <!-- DataTemplate for decimals -->
        <DataTemplate DataType="{x:Type sys:Decimal}">
            <!-- <TextBox Text="{Binding Path=.}" MinWidth="50" HorizontalAlignment="Stretch" />-->
            <dxe:TextEdit Text="{Binding Path=.}" MinWidth="50" Mask="f" MaskType="Numeric" HorizontalAlignment="Stretch" />
        </DataTemplate>
        <!-- DataTemplate for DateTimes -->
        <DataTemplate DataType="{x:Type sys:DateTime}">
            <DataTemplate.Resources>
                <DataTemplate DataType="{x:Type sys:String}">
                    <TextBlock Text="{Binding Path=.}"/>
                </DataTemplate>
            </DataTemplate.Resources>
            <DatePicker SelectedDate="{Binding Path=.}" HorizontalAlignment="Stretch"/>
        </DataTemplate>
        </UserControl.Resources>
    <ContentPresenter Content="{Binding MyChangingPropery}"/>
    </UserControl>
    

    更多关于2的信息:

    我想在 View 中有一个标签和一个根据对象而变化的属性。像这样的东西:
    <UserControl> 
        <UserControl.Resources>
            <!-- ...DataTemplate here... -->
        </UserControl.Resources>
        <StackPanel>
            <Label Content="Allo"/>
            <ContentPresenter Content="{Binding MyChangingPropery}"/>
        </StackPanel>
    </UserControl>
    

    但是如果我把DataTemplate放在这个UserControl资源上,也会影响到Label“allo”。所以我必须创建另一个包含 DataTemplate 和 MyChangingProperty 的 View ,以便标签 Allo 不会受到影响。但是为一个属性创建的额外 View 对我来说有点难看,我确信有一种更好的方法来隔离 DataTemplate,以便它只能应用于一个 UIControl。
    <UserControl >
        <StackPanel>
            <Label Content="Allo"/>
            <ContentPresenter Content="{Binding MyContainerViewModel}"/>
        </StackPanel>
    </UserControl>
    

    注意:这里的 MyContainerViewModel 与描述的第一个 View 相关联。

    提前致谢!

    最佳答案

    一种可能的解决方案是使用 DataTemplateSelector .您不能使用两种方式绑定(bind)原始类型,因为这必须以某种方式通过 DataTemplate 进行引用。我认为 WPF 不支持。
    DataTemplateSelector现在选择正确的DataTemplate根据属性类型搜索权限DataTemplate按名称在资源中。这也解决了您的问题,您的 DataTemplatesLabel 互动.

    所以首先你需要定义一个 DataTemplateSelector这改变了DataTemplate根据房产类型:

    public class MyDataTemplateSelector : DataTemplateSelector
    {
        public override DataTemplate SelectTemplate(object item, DependencyObject container)
        {
            var fe = (FrameworkElement)container;
            var prop = (item as MyViewModelType)?.MyChangingProperty;
            if (prop is string)
                return fe.FindResource("MyStringDT") as DataTemplate;
            else if (prop is bool)
                return fe.FindResource("MyBoolDT") as DataTemplate;
            // More types...
            return base.SelectTemplate(item, container);
        }
    }
    

    然后你需要更改UserControl像这样:
    <UserControl>
        <UserControl.Resources>
            <local:MyDataTemplateSelector x:Key="MyDTSelector" />
            <!-- DataTemplate for strings -->
            <DataTemplate x:Key="MyStringDT">
                <TextBox Text="{Binding MyChangingProperty, Mode=TwoWay}"
                    HorizontalAlignment="Stretch"/>
            </DataTemplate>
            <!-- DataTemplate for bool -->
            <DataTemplate x:Key="MyBoolDT">
                <CheckBox IsChecked="{Binding MyChangingProperty, Mode=TwoWay}" />
            <!-- More DataTemplates... -->
            </DataTemplate>
        </UserControl.Resources>
        <StackPanel>
            <Label Content="Allo"/>
            <ContentPresenter Content="{Binding MyContainerViewModel}"
                ContentTemplateSelector="{StaticResource MyDTSelector}" />
        </StackPanel>
    </UserControl>
    

    您可以找到有关 DataTemplateSelector 的更多信息。 here .

    当然也可以设置DataType在这个新的DataTemplates但它不是必需的,因为 x:Key无论如何,它们都是独一无二的。但如果你愿意,它必须看起来像这样:
    <DataTemplate x:Key="MyStringDT" DataType="{x:Type local:MyViewModelType}">
    

    关于wpf - DataTemplate 绑定(bind)取决于属性类型和工作属性绑定(bind),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40003144/

    相关文章:

    c# - 如何在 WPF 中制作 TextBlock 滚动条

    c# - 将值从窗口返回到 WPF 类

    wpf - 如何设置文本 block 自动调整大小以适应 TreeView 的宽度?

    c# - 我的以 Xamarin 为目标的 UWP 应用缺少选项卡

    c# - 将 silverlight 动态动画移动到 WPF

    wpf - 空代码隐藏是什么?

    xamarin - Xamarin表单MVVM验证带有繁忙指示符的表单

    c# - 在长时间未使用后保持 .NET alt-tab 替换响应的策略?

    c# - 要命令的 XAML Setter 属性

    wpf - 如何确保所有模型都可以访问服务代理?