我希望数据模板显示通常的内容,只是当用户在某些窗口中时,我想删除(隐藏)某些UI元素。我想知道如何访问数据模板来进行这样的编辑。我已经知道如何访问模板显示的对象(绑定数据源),只需要模板即可。
我的添加新计算机窗口:
private void OnInit(object sender, RoutedEventArgs e)
{
this.DataContext = new MachineItem("Type your description here",
MachineTypeEnum.Computer, "1.1.1.1", "1.1.1.1", 4, null, ((GUIApp)Application.Current).CurrentMachineGroup,
BordersStyle.Blue);
//Below are 2 lines that sudo represent what I am trying to do.
var template = this.DataContext as TheTemplateIWant; //Wrong
template.DeleteButton.Visibility = Visibility.Hidden; //I don't need a delete button on something I am trying to add
}
我知道我可以执行的另一种方法是更改“ MachineItem”对象的属性,然后在模板中创建DataTrigger以基于该属性编辑UI(我可以使用bool),但这似乎是有点骇人听闻,因为MachineItem对象表示 data ,并且不必跟踪其所在的窗口。除了在OnInit()中进行编辑外,我还接受其他方法,只要这是一个好习惯
答案 0 :(得分:0)
一种选择是对该窗口使用不同的DataTemplate
,在Window.Resources
中覆盖它。
或者,您可以在将窗口渲染/附加到DataTemplate
后在VisualTree
中找到 <DataTemplate DataType="{x:Type local:MachineItem}">
<StackPanel>
<TextBlock Text="{Binding Id}"></TextBlock>
<TextBlock Text="{Binding Name}"></TextBlock>
<Button x:Name="DeleteButton"> delete</Button>
</StackPanel>
</DataTemplate>
个元素。
要实现此目的,您可以按类型,名称查找Window元素。 例如,如果您的DataTemplate包含一些元素,并且按钮的名称为
VisualTreeHelper
您可以像使用VisualTreeHelperExtensions.FindChild<Button>(this, "DeleteButton");
在窗口中找到DeleteButtons一样
public static class VisualTreeHelperExtensions
{
public static IEnumerable<T> FindChild<T>(DependencyObject parent, string childName)
where T : DependencyObject
{
// Confirm parent and childName are valid.
if (parent == null)
{
yield break;
}
int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < childrenCount; i++)
{
var child = VisualTreeHelper.GetChild(parent, i);
// If the child is not of the request child type child
T childType = child as T;
if (childType == null)
{
// recursively drill down the tree
foreach (var innerChild in FindChild<T>(child, childName))
{
yield return innerChild;
}
}
else if (!string.IsNullOrEmpty(childName))
{
var frameworkElement = child as FrameworkElement;
// If the child's name is set for search
if (frameworkElement != null && frameworkElement.Name == childName)
{
// if the child's name is of the request name
yield return (T)child;
}
}
else
{
// child element found.
yield return (T)child;
}
}
}
}
我已经找到了here的VisualTreeHelper扩展的修改版本,该扩展会返回按类型列出的所有元素
private void OnInit(object sender, RoutedEventArgs e)
{
this.DataContext = new MachineItem("Type your description here",
MachineTypeEnum.Computer, "1.1.1.1", "1.1.1.1", 4, null, ((GUIApp)Application.Current).CurrentMachineGroup,
BordersStyle.Blue);
var buttons = VisualTreeHelperExtensions.FindChild<Button>(this, "DeleteButton");
foreach (var button in buttons)
{
button.Visibility = Visibility.Hidden;
}
}
如此完整的示例(具有上面定义的模板):
Items
答案 1 :(得分:0)
您可以使用FrameworkElement.FindResource
通过名称查找“最近”的资源。这将搜索XAML中所有祖先元素中的所有<x.Resources>
集合,包括App.xaml
中定义的集合。最终将以与您在XAML代码中使用静态资源完全相同的方式来解析资源。
从MSDN:
使用指定的键搜索资源,并引发 如果找不到请求的资源,则为异常。
...
如果在调用元素上找不到资源,则父级 接下来搜索逻辑树中的元素,然后搜索应用程序, 然后是主题,最后是系统资源。此查找方法是 与如果资源请求者搜索树的方式相同 标记中的动态资源引用。有关更多信息 资源查找,请参阅XAML资源。
通常,您立即将FindResource返回值转换为 您使用返回的资源设置的属性的类型 值。
资源键不一定是字符串。例如, 主题级别的控件故意键入到 控件,以及控件通常使用的应用程序或页面样式 相同的关键约定。有关详细信息,请参见样式和模板化或 XAML资源。
在您的示例中,它看起来像:
var template = this.FindResource("TheTemplateIWant") as DataTemplate;
所有这些,您可能最好使用数据绑定,并将元素的可见性绑定到视图模型的属性,而不是尝试通过编程来操纵模板。