我有以下(有效的)XAML
定义:
<DataGridTemplateColumn Header="Station & Programm" Width="*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ListBox
ItemsSource="{Binding Targets}"
Style="{StaticResource ListBoxTransparentStyle}"
VerticalAlignment="Center"
IsHitTestVisible="False"> <!--Disable Selection-->
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="A"/>
<ColumnDefinition Width="5"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock
Grid.Column="0"
Text="{Binding Station}"
Height="Auto"/>
<TextBlock
Grid.Column="2"
Text="{Binding Program}"
Height="Auto"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
我想将此DataTemplate
外包,并使用以下DataTemplateSelector
:
public class ZlsRouteEditorDataTemplateSelector : DataTemplateSelector
{
public DataTemplate ViewDataTemplate { get;set; }
public DataTemplate EditDataTemplate { get; set; }
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
if (item is ERouteEditor e)
{
switch (e)
{
case ERouteEditor.View:
return ViewDataTemplate;
case ERouteEditor.Edit:
return EditDataTemplate;
default:
throw new ArgumentOutOfRangeException();
}
}
return base.SelectTemplate(item, container);
}
}
然后,我将代码更改如下:
<ControlTemplate>
<ControlTemplate.Resources>
<DataTemplate x:Key="StationProgramView" x:Shared="True">
<ListBox
ItemsSource="{Binding Targets}"
Style="{StaticResource ListBoxTransparentStyle}"
VerticalAlignment="Center"
IsHitTestVisible="False"> <!--Disable Selection-->
<ListBox.ItemTemplate>
<DataTemplate>
<Grid >
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="A"/>
<ColumnDefinition Width="5"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<controls:HtTextfeld
Grid.Column="0"
Text="{Binding Station}"
DisableTranslation="True"
Height="Auto"/>
<controls:HtTextfeld
Grid.Column="2"
Text="{Binding Program}"
DisableTranslation="True"
Height="Auto"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</DataTemplate>
<DataTemplate x:Key="StationProgramEdit" x:Shared="True">
<TextBlock Text="Hello World"></TextBlock>
</DataTemplate>
<recipeControls:ZlsRouteEditorDataTemplateSelector x:Key="StationProgramTemplateSelector" ViewDataTemplate="{StaticResource StationProgramView}" EditDataTemplate="{StaticResource StationProgramEdit}"/>
<DataGridTemplateColumn Header="Station & Programm" Width="*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ContentControl
ContentTemplateSelector="{StaticResource StationProgramTemplateSelector}"
Content="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=recipeControls:ZlsRouteEditor}, Path=Mode}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
正确选择了DataTemplate
,但是数据绑定不再起作用。
答案 0 :(得分:1)
尝试设置列的CellTemplateSelector
属性,而不是将CellTemplate
设置为ContentControl
:
<DataGridTemplateColumn Header="Station & Programm" Width="*" CellTemplateSelector="{StaticResource StationProgramTemplateSelector}" />
DataContext
的{{1}}中根元素的ContentTemplate
是同一ContentControl
的{{1}}。
答案 1 :(得分:0)
这是我的个人解决方案,如何使其正常工作。
我已经更改了ZlsRouteEditorDataTemplateSelector
类,使其能够查找我的特定控件(ZlsRouteEditor
)并获得Mode
值。
public class ZlsRouteEditorDataTemplateSelector : DataTemplateSelector
{
public DataTemplate ViewDataTemplate { get;set; }
public DataTemplate EditDataTemplate { get; set; }
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
if (item is ERouteEditor e)
return _GetTemplate(e);
ZlsRouteEditor parent = container.TryFindParent<ZlsRouteEditor>();
if (parent != null)
return _GetTemplate(parent.Mode);
return base.SelectTemplate(item, container);
}
private DataTemplate _GetTemplate(ERouteEditor e)
{
switch (e)
{
case ERouteEditor.View:
return ViewDataTemplate;
case ERouteEditor.Edit:
return EditDataTemplate;
default:
throw new ArgumentOutOfRangeException();
}
}
}
/// <summary>
/// Finds a parent of a given item on the visual tree.
/// </summary>
/// <typeparam name="T">The type of the queried item.</typeparam>
/// <param name="child">A direct or indirect child of the
/// queried item.</param>
/// <returns>The first parent item that matches the submitted
/// type parameter. If not matching item can be found, a null
/// reference is being returned.</returns>
public static T TryFindParent<T>(this DependencyObject child) where T : DependencyObject
{
//get parent item
DependencyObject parentObject = GetParentObject(child);
//we've reached the end of the tree
if (parentObject == null) return null;
//check if the parent matches the type we're looking for
T parent = parentObject as T;
if (parent != null)
{
return parent;
}
else
{
//use recursion to proceed with next level
return TryFindParent<T>(parentObject);
}
}
然后直接调用它(如 mm8 所述)
<DataGridTemplateColumn Header="Station & Programm" Width="*" CellTemplateSelector="{StaticResource StationProgramTemplateSelector}"/>
在哪里,为什么以及何时需要Mode属性?
我已将recipe
对象绑定到ZlsRouteEditor
控件以查看或编辑 recipe
。
为避免多个控件或Styles
(ZlsRouteEditorView
,ZlsRouteEditorEdit
...),我在enum
中将ERouteEditor
DependencyProperty
设为ZlsRouteEditor
DataTemplates
来更改Template
内部特定区域的<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<recipeControls:ZlsRouteEditor Height="570" Margin="5" Mode="View"/>
<recipeControls:ZlsRouteEditor Height="570" Margin="5" Mode="Edit"/>
</StackPanel>
。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:local="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<MvxListView
android:layout_height="match_parent"
android:layout_width="match_parent"
android:divider="#000000"
android:dividerHeight="3px"
local:MvxBind="ItemsSource Weather; ItemClick ListItemClickCommand"
local:MvxItemTemplate="ItemTemplateId weatherListItem"
SelectedItem="{mvx:MvxBind CurrentWeather}"/>
</LinearLayout>