我有以下類工作:創建WPF DataTemplate中取決於類屬性具體類型(不是類類型)
public class ConcreteClassFoo
{
public ObservableCollection<ConcreteComponent> Components { get; set; }
}
public class ConcreteComponent
{
IAttribute Foo { get; set; }
}
public class ConcreteAttribute1 : IAttribute {}
public class ConcreteAttribute2 : IAttribute {}
在我的XAML映射:
<ListView ItemsSource={Bindings Components} />
正如你所看到的,我的ListBox
將Components
屬性綁定爲ItemsSource
。
的Components
屬性是ConcreteComponent
該HAS-A抽象類型IAttribute
的屬性Foo
的集合。
我想更改ListView
模板,具體取決於我的屬性Foo
的具體類別。
隨着DataTemplate
有可能取決於類具體類型構建不同的模板,例如:
<DataTemplate DataType="{x:Type ConcreteComponent1}" />
<DataTemplate DataType="{x:Type ConcreteComponent2}" />
但怎麼可能取決於具體類屬性類型建立不同的模板?
UPDATE:
添加對我的實際問題一些相關信息。
我有一個ListView
包含一個ObservableCollection<BaseWindowShape>
叫Shapes
。對象有一個屬性AdditionalData
(AdditionalData
是抽象的),可以是DistanceAdditionalData
或TermoAdditionalData
。
我想這取決於AdditionalData
具體類型(在ListView
共享所有相同的混凝土AdditionalData
)改變澈ListView
視圖。
因此,如果第一形狀的AdditionalData
,例如,是DistanceAtdditionalData
我想有三列
否則,我想只有兩個列
MaxDistance
and MinAreaPercent
are DistanceAdditionalData
attributes,while MaxTemperature
is a TermoAdditionalData
屬性。
我嘗試以下列方式實現此行爲,但它不起作用。
我該如何解決我的問題?
<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>
更新2: 我使用lokusking答案更新我的實現,那就是:
<ListView ItemsSource="{Binding FirstComponent}">
<ListView.Resources>
<DataTemplate DataType="{x:Type local:ConcreteAttribute1}">
<ListView ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=Components}">
<ListView.View>
<GridView>
<GridViewColumn Header="1 column">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Foo.Name, Mode=OneWay}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="2 column">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBox Text="{Binding Foo.Number, Mode=OneWay}"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
</DataTemplate>
<DataTemplate DataType="{x:Type local:ConcreteAttribute2}">
<ListView ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=Components}">
<ListView.View>
<GridView>
<GridViewColumn Header="3 column">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Foo.Name, Mode=OneWay}"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="4 column">
<GridViewColumn.CellTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding Foo.B, Mode=OneWay}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
</DataTemplate>
</ListView.Resources>
<ListView.ItemTemplate>
<DataTemplate>
<ContentControl Content="{Binding Foo}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
我加宣佈了一個名爲FirstComponent
屬性爲:
public ObservableCollection<ConcreteComponent> FirstComponent { get; } = new ObservableCollection<ConcreteComponent> { Components.First() };
並將其綁定爲我的第一個0123的。 作爲DataTemplate
爲FirstComponent
我宣佈另一個ListView
,綁定到集合Components
爲了有不同的列取決於它。 如果我收藏的第一個元素的ConcreteAttribute1
我有以下結果的屬性:下一個
否則:
也許它不是最好的辦法實現這個結果(我必須聲明一個ObservableCollection
只有一個元素才能檢查它),但它的工作原理。
我認爲這是非常接近解決我的問題。我更新了我的問題,在答案後添加了更多信息和我的(錯誤)實現,告訴我是否現在一切都清楚了,如果你能給我一些建議,那麼解決我的問題。非常感謝! – Rowandish
@Rowandish更新後發佈 – lokusking
@lokuskinig它完美的工作,謝謝!爲了解決我的實際問題,我使用集合的第一個元素創建了一個ListView,以決定創建哪種列(參見我的第二個更新);我不認爲這是解決問題的最好方法,但實際上它是有效的。如果你有一個更優雅的方式來達到相同的結果,那就太棒了! – Rowandish