最后更新了一个简单示例
我有一个渲染到画布中的对象列表。该对象包含另一个基类
的对象public class FooBase()
{
}
public class Foo1 : FooBase()
{
}
public class Foo2 : FooBase()
{
public ICollection<Bar> BarList() { get;set; }
}
public class Bar
{
public BarIdentifier BarIdentifier {get; set;}
public int Value1 {get; set;}
public string Value2 {get; set; }
}
public class HolderClass()
{
public FooBase FooClass() { get; set; }
public int PosX {get;set;}
public int PosY {get;set;}
}
在我的模型中,我还有一个活跃的Bar类选择。这是通过使用下拉菜单设置的。我还有一个HolderClasses列表
public BarIdentifier SelectedBar {get;set;}
public List<ValveSystemOverviewGridContent> HolderList {get;set;}
在我的标记/ xaml中我有这个
<ItemsControl ItemsSource="{Binding HolderList}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="Canvas.Left" Value="{Binding Path=XPos, Mode=OneWay}" />
<Setter Property="Canvas.Top" Value="{Binding Path=YPos, Mode=OneWay}" />
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
和datatemplates as this
<UserControl.Resources>
<DataTemplate DataType="{x:Type entities:Foo1 }" >
<Border BorderBrush="Black" BorderThickness="1">
<StackPanel Orientation="Horizontal" >
<Label Content="FooClass 1" />
</StackPanel>
</Border>
</DataTemplate>
<DataTemplate DataType="{x:Type entities:Foo2 }">
<Border CornerRadius="4" Background="White" BorderThickness="2" BorderBrush="{DynamicResource NormalBorderBrush}" >
<StackPanel Orientation="Vertical">
<Label Content="Foo Class 2" />
<Label Content="{Binding ????" />
</StackPanel>
</Border>
</DataTemplate>
<DataTemplate DataType="{x:Type entities:HolderClass }">
<StackPanel Orientation="Horizontal" >
<Label Content="This is Holder Class" FontWeight="Bold" />
<ContentControl Content="{Binding Path=FooClass}" />
</StackPanel>
</DataTemplate>
</UserControl.Resources>
我想在FooBar2数据模板中做的是获取BarList中与SelectedBar匹配的项目之一。我通常会使用
来做这件事BarList.First(b => b.BarIdentifier.Id == modelView.SelectedBar.Id);
有没有办法在我的数据模板中完成此过滤器/选择并以有效的方式显示Bar的Value1和Value2?
如果我更改主视图中的下拉列表,我想显示与BarIdentifier匹配的栏
使用示例更新
根据要求,我试着做一个简短的例子。包含函数GetCalcDataForCondition如何根据所选条件过滤掉CalcData。
MainWindow.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace FilterSample
{
public class CalcData
{
public Condition Condition { get; set; }
public int Diameter { get; set; }
public string Name { get; set; }
}
public class Condition
{
public int Id { get; set; }
public string Name { get; set; }
}
public class BaseClass
{
public string Name { get; set; }
}
class TagClass : BaseClass
{
}
class ConnectionClass : BaseClass
{
public List<CalcData> CalcData { get; set; }
}
public class Holder
{
public int PosX { get; set; }
public int PosY { get; set; }
public BaseClass Content { get; set; }
}
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public List<Condition> Conditions { get; set; }
public List<Holder> Holders { get; set; }
public int SelectedConditionId { get; set; }
private void GenerateData()
{
Conditions = new List<Condition>();
Conditions.Add(new Condition() { Id = 1, Name = "Condition 1" });
Conditions.Add(new Condition() { Id = 2, Name = "Condition 2" });
Conditions.Add(new Condition() { Id = 3, Name = "Condition 3" });
Conditions.Add(new Condition() { Id = 4, Name = "Condition 4" });
Conditions.Add(new Condition() { Id = 5, Name = "Condition 5" });
Holders = new List<Holder>();
Holders.Add(new Holder() { PosX = 10, PosY = 10, Content = new TagClass() { } });
Holders.Add(new Holder() { PosX = 10, PosY = 110, Content = GenerateConnectionClass(1, Conditions) });
Holders.Add(new Holder() { PosX = 10, PosY = 210, Content = new TagClass() { } });
Holders.Add(new Holder() { PosX = 10, PosY = 310, Content = GenerateConnectionClass(2, Conditions) });
Holders.Add(new Holder() { PosX = 10, PosY = 410, Content = new TagClass() { } });
}
private ConnectionClass GenerateConnectionClass(int index, List<Condition> conditions)
{
var conn = new ConnectionClass();
conn.Name = "Connection " + index;
conn.CalcData = new List<CalcData>();
foreach (var c in conditions)
{
conn.CalcData.Add(new CalcData() { Condition = c, Name = "Calc values for condition " + c.Id, Diameter = c.Id * 100 });
}
return conn;
}
private CalcData GetCalcDataForCondition(ConnectionClass conn, Condition condition)
{
return conn.CalcData.First(c => c.Condition.Id == condition.Id);
}
public MainWindow()
{
GenerateData();
SelectedConditionId = 1;
InitializeComponent();
DataContext = this;
}
}
}
MainWindow.xaml
<Window x:Class="FilterSample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:FilterSample"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<DataTemplate DataType="{x:Type local:TagClass }" >
<Border BorderBrush="Black" BorderThickness="1">
<StackPanel Orientation="Horizontal" >
<Label Content="Tag Class" />
</StackPanel>
</Border>
</DataTemplate>
<DataTemplate DataType="{x:Type local:ConnectionClass }">
<Border CornerRadius="4" Background="White" BorderThickness="2" BorderBrush="{DynamicResource NormalBorderBrush}" >
<StackPanel Orientation="Vertical">
<Label Content="Connection Class" />
<Label Content="HERE I WANT TO DISPLAY related CalcData.Name" />
</StackPanel>
</Border>
</DataTemplate>
<DataTemplate DataType="{x:Type local:Holder }">
<StackPanel Orientation="Horizontal" >
<Label Content="This is Holder Class" FontWeight="Bold" />
<ContentControl Content="{Binding Path=Content}" />
</StackPanel>
</DataTemplate>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="50" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal">
<Label Content="Select condition " Height="24" />
<ComboBox ItemsSource="{Binding Conditions}" SelectedValue="{Binding SelectedConditionId}" DisplayMemberPath="Name" SelectedValuePath="Id" Width="200" Height="24" />
</StackPanel>
<ItemsControl ItemsSource="{Binding Holders}" Grid.Row="1">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="Canvas.Left" Value="{Binding Path=PosX , Mode=OneWay}" />
<Setter Property="Canvas.Top" Value="{Binding Path=PosY, Mode=OneWay}" />
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
</Grid>
</Window>
答案 0 :(得分:1)
基本上,您需要一些方式将所选条件ID传输到内部数据模板。我的建议:让DataTemplate
的{{1}}取决于所选条件(将其从资源移至内容Holder
)并为<ItemsControl.ItemTemplate>
创建UserControl
。将Holder
添加到usercontrol并分配它:
SelectedConditionId
将您的大部分内容移至持有人控件中,并使用<Window
...>
<Grid x:Name="grid1">
<Grid.RowDefinitions>
<RowDefinition Height="50" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal">
<Label Content="Select condition " Height="24" />
<ComboBox x:Name="condSelector" ItemsSource="{Binding Conditions}" SelectedValue="{Binding SelectedConditionId}" DisplayMemberPath="Name" SelectedValuePath="Id" Width="200" Height="24" />
</StackPanel>
<ItemsControl ItemsSource="{Binding Holders}" Grid.Row="1">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="Canvas.Left" Value="{Binding Path=PosX , Mode=OneWay}" />
<Setter Property="Canvas.Top" Value="{Binding Path=PosY, Mode=OneWay}" />
</Style>
</ItemsControl.ItemContainerStyle>
<!-- Here it is -->
<ItemsControl.ItemTemplate>
<DataTemplate>
<local:HolderControl DataContext="{Binding}" SelectedConditionId="{Binding ElementName=condSelector,Path=SelectedValue}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</Window>
SelectedConditionId
来获取所选MultiBinding
:
CalcData
代码背后:
<UserControl
....
x:Name="uc1">
<UserControl.Resources>
<local:SelectedCalcDataConverter x:Key="calcDataSelector"/>
<DataTemplate DataType="{x:Type local:TagClass }" >
<Border BorderBrush="Black" BorderThickness="1">
<StackPanel Orientation="Horizontal" >
<Label Content="Tag Class" />
</StackPanel>
</Border>
</DataTemplate>
<DataTemplate DataType="{x:Type local:ConnectionClass }">
<Border CornerRadius="4" Background="White" BorderThickness="2" BorderBrush="{DynamicResource NormalBorderBrush}" >
<StackPanel Orientation="Vertical">
<StackPanel.DataContext>
<MultiBinding Converter="{StaticResource calcDataSelector}" Mode="OneWay">
<Binding Path="CalcData"/>
<Binding ElementName="uc1" Path="SelectedConditionId"/>
</MultiBinding>
</StackPanel.DataContext>
<Label Content="Connection Class" />
<!--Label Content="HERE I WANT TO DISPLAY related CalcData.Name" /-->
<Label Content="{Binding Name}"/>
</StackPanel>
</Border>
</DataTemplate>
</UserControl.Resources>
<Grid>
<StackPanel Orientation="Horizontal" >
<Label Content="This is Holder Class" FontWeight="Bold" />
<ContentControl Content="{Binding Path=Content}" />
</StackPanel>
</Grid>
</UserControl>
转换器:
public partial class HolderControl : UserControl
{
public HolderControl()
{
InitializeComponent();
}
public int? SelectedConditionId
{
get { return (int?)GetValue(SelectedConditionIdProperty); }
set { SetValue(SelectedConditionIdProperty, value); }
}
// Using a DependencyProperty as the backing store for SelectedConditionId. This enables animation, styling, binding, etc...
public static readonly DependencyProperty SelectedConditionIdProperty =
DependencyProperty.Register("SelectedConditionId", typeof(int?), typeof(HolderControl), new FrameworkPropertyMetadata());
}
还有其他方法来传输选定的ID,但这个方法相对容易理解。