Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 根据类属性具体类型(非类类型)创建WPF数据模板_C#_Wpf_Datatemplate - Fatal编程技术网

C# 根据类属性具体类型(非类类型)创建WPF数据模板

C# 根据类属性具体类型(非类类型)创建WPF数据模板,c#,wpf,datatemplate,C#,Wpf,Datatemplate,我正在学习以下课程: public class ConcreteClassFoo { public ObservableCollection<ConcreteComponent> Components { get; set; } } public class ConcreteComponent { IAttribute Foo { get; set; } } public class ConcreteAttribute1 : IAttribute {} publi

我正在学习以下课程:

public class ConcreteClassFoo
{
    public ObservableCollection<ConcreteComponent> Components { get; set; }
}

public class ConcreteComponent
{
    IAttribute Foo { get; set; }
}

public class ConcreteAttribute1 : IAttribute {}
public class ConcreteAttribute2 : IAttribute {}
但是,如何根据具体的类属性类型构建不同的模板呢

更新

我补充了一些关于我实际问题的信息

我有一个
列表视图
包含一个名为
形状
可观察集合
。对象
BaseWindowShape
具有一个属性
AdditionalData
AdditionalData
是抽象的),该属性可以是
DistanceAdditionalData
TermLoaditionalData

我想根据
附加数据
具体类型更改che
列表视图
视图(
列表视图
中的所有
基本窗口形状
共享相同的具体
附加数据

因此,如果第一个形状的
AdditionalData
DistanceAtAdditionalData
,我希望有三列

否则我只想有两列

MaxDistance
MinAreaPercent
DistanceAdditionalData
属性,而
MaxTemperature
TermLoadAdditionalData
属性

我尝试以以下方式实现此行为,但它不起作用

我怎样才能解决我的问题

<ListView ItemsSource="{Binding Shapes}">
  <ListView.Resources>
        <DataTemplate DataType="{x:Type additionalData:TridimensionalAdditionalData}">
            <ListView>
                <ListView.View>
                    <GridView>
                        <GridViewColumn Header="Level">
                            <GridViewColumn.CellTemplate>
                                <DataTemplate>
                                    <wpfControls:DigitInput Value="{Binding Level, Mode=TwoWay}" />
                                </DataTemplate>
                            </GridViewColumn.CellTemplate>
                        </GridViewColumn>
                        <GridViewColumn Header="Max Distance">
                            <GridViewColumn.CellTemplate>
                                <DataTemplate>
                                    <StackPanel>
                                        <xctk:DoubleUpDown Value="{Binding MaxDistance}"/>
                                        <TextBlock Text="mm">
                                    </StackPanel>
                                </DataTemplate>
                            </GridViewColumn.CellTemplate>
                        </GridViewColumn>
                        <GridViewColumn Header="Min Area">
                            <GridViewColumn.CellTemplate>
                                <DataTemplate>
                                    <xctk:DoubleUpDown Value="{Binding MinAreaPercent}" />
                                </DataTemplate>
                            </GridViewColumn.CellTemplate>
                        </GridViewColumn>
                        </GridView>
                </ListView.View>
            </ListView>
        </DataTemplate>
        <DataTemplate DataType="{x:Type additionalData:ThermalAdditionalData}">
            <ListView>
                <ListView.View>
                    <GridView>
                        <GridViewColumn Header="Level">
                            <GridViewColumn.CellTemplate>
                                <DataTemplate>
                                    <wpfControls:DigitInput Value="{Binding Level, Mode=TwoWay}" />
                                </DataTemplate>
                            </GridViewColumn.CellTemplate>
                        </GridViewColumn>
                        <GridViewColumn Header="Max Temperature">
                            <GridViewColumn.CellTemplate>
                                <DataTemplate>
                                    <StackPanel>
                                        <xctk:DoubleUpDown Value="{Binding MaxTemperature}"/>
                                        <TextBlock Text=" °F"/>
                                    </StackPanel>
                                </DataTemplate>
                            </GridViewColumn.CellTemplate>
                        </GridViewColumn>
                    </GridView>
                </ListView.View>
            </ListView>
        </DataTemplate>
    </ListView.Resources>
    <ListView.ItemTemplate>
        <DataTemplate>
            <ContentControl Content="{Binding AdditionalData}" />
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>
并将其绑定为我的第一个
列表视图的
ItemsSource
。 作为
第一个组件的
数据模板
,我声明了另一个
列表视图
,绑定到集合
组件
,以便根据它有不同的列。 如果集合的第一个元素的属性为
ConcreteAttribute1
,则会得到以下结果:

否则,请执行以下操作:


可能这不是实现此结果的最佳方法(我必须声明一个只包含一个元素的
可观察集合
,以检查它),但它是有效的。

由于我没有真正获得您想要的结果,我只能猜测,这就是您想要做的:

<ListView ItemsSource="{Binding Components}">
            <ListView.Resources>
                <DataTemplate DataType="{x:Type ConcreteAttribute1}">
                    <TextBlock Text="Con1"></TextBlock>
                </DataTemplate>
                <DataTemplate DataType="{x:Type ConcreteAttribute2}">
                    <TextBlock Text="Con2"></TextBlock>
                </DataTemplate>
            </ListView.Resources>
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ContentControl Content="{Binding Foo}"></ContentControl>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
XAML

<ListView ItemsSource="{Binding Components}">
    <ListView.Resources>
        <DataTemplate DataType="{x:Type ConcreteAttribute1}">
            <StackPanel>
                <TextBlock Text="{Binding Name, Mode=OneWay}"/>
                <TextBox Text="{Binding Number, Mode=OneWay}"></TextBox>
            </StackPanel>
        </DataTemplate>
        <DataTemplate DataType="{x:Type ConcreteAttribute2}">
            <StackPanel>
                <TextBlock Text="{Binding Name, Mode=OneWay}"/>
                <CheckBox IsChecked="{Binding B, Mode=OneWay}"></CheckBox>
            </StackPanel>
        </DataTemplate>
    </ListView.Resources>
    <ListView.ItemTemplate>
        <DataTemplate>
            <ContentControl Content="{Binding Foo}" />
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

用法

public MainWindow() {
      InitializeComponent();
      this.Components = new ObservableCollection<ConcreteComponent>();
      this.Components.Add(new ConcreteComponent { Foo = new ConcreteAttribute1() });

      this.Components.Add(new ConcreteComponent { Foo = new ConcreteAttribute2() });


      this.DataContext = this;
    }

    public ObservableCollection<ConcreteComponent> Components {
      get;
    }
public主窗口(){
初始化组件();
this.Components=新的ObservableCollection();
Add(new-ConcreteComponent{Foo=new-ConcreteAttribute1()});
Add(new-ConcreteComponent{Foo=new-ConcreteAttribute2()});
this.DataContext=this;
}
公共可观测集合组件{
得到;
}
结果

注意

public MainWindow() {
      InitializeComponent();
      this.Components = new ObservableCollection<ConcreteComponent>();
      this.Components.Add(new ConcreteComponent { Foo = new ConcreteAttribute1() });

      this.Components.Add(new ConcreteComponent { Foo = new ConcreteAttribute2() });


      this.DataContext = this;
    }

    public ObservableCollection<ConcreteComponent> Components {
      get;
    }
确保你没有打字错误。
如果它仍然不工作,可能是错误输出和/或异常的后屏幕

我认为它很快就能解决我的问题。我更新了我的问题,添加了更多的信息和我的(错误的)实现,在你的回答之后,告诉我现在是否一切都清楚了,如果你能给我一些建议来解决我的问题。非常感谢@罗文迪什语更新Post@lokuskinig非常好用,谢谢!为了解决实际问题,我使用集合的第一个元素在另一个列表视图中创建了一个列表视图,以决定创建哪种列(请参阅我的第二次更新);我不认为这是解决问题的最好方法,但实际上它是有效的。如果你有一个更优雅的方式来实现同样的结果,那将是伟大的!如果您想基于类型以外的其他内容选择模板,您可能会发现它也很有用。例如,关于字符串属性的值
<ListView ItemsSource="{Binding Components}">
            <ListView.Resources>
                <DataTemplate DataType="{x:Type ConcreteAttribute1}">
                    <TextBlock Text="Con1"></TextBlock>
                </DataTemplate>
                <DataTemplate DataType="{x:Type ConcreteAttribute2}">
                    <TextBlock Text="Con2"></TextBlock>
                </DataTemplate>
            </ListView.Resources>
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ContentControl Content="{Binding Foo}"></ContentControl>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
public class ConcreteComponent {
    public IAttribute Foo {
      get; set;
    }
  }

  public class ConcreteAttribute1 : IAttribute {
    public string Name => "ConAtt 1";
    public int Number => 999;

  }
  public class ConcreteAttribute2 : IAttribute {
    public string Name => "ConAtt 2";
    public bool B => true;

  }

  public interface IAttribute {
    string Name {
      get;
    }
  }
<ListView ItemsSource="{Binding Components}">
    <ListView.Resources>
        <DataTemplate DataType="{x:Type ConcreteAttribute1}">
            <StackPanel>
                <TextBlock Text="{Binding Name, Mode=OneWay}"/>
                <TextBox Text="{Binding Number, Mode=OneWay}"></TextBox>
            </StackPanel>
        </DataTemplate>
        <DataTemplate DataType="{x:Type ConcreteAttribute2}">
            <StackPanel>
                <TextBlock Text="{Binding Name, Mode=OneWay}"/>
                <CheckBox IsChecked="{Binding B, Mode=OneWay}"></CheckBox>
            </StackPanel>
        </DataTemplate>
    </ListView.Resources>
    <ListView.ItemTemplate>
        <DataTemplate>
            <ContentControl Content="{Binding Foo}" />
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>
public MainWindow() {
      InitializeComponent();
      this.Components = new ObservableCollection<ConcreteComponent>();
      this.Components.Add(new ConcreteComponent { Foo = new ConcreteAttribute1() });

      this.Components.Add(new ConcreteComponent { Foo = new ConcreteAttribute2() });


      this.DataContext = this;
    }

    public ObservableCollection<ConcreteComponent> Components {
      get;
    }