从OnInit窗口中的WPF编辑数据模板

时间:2019-02-06 16:58:11

标签: c# wpf xaml

我希望数据模板显示通常的内容,只是当用户在某些窗口中时,我想删除(隐藏)某些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()中进行编辑外,我还接受其他方法,只要这是一个好习惯

2 个答案:

答案 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;

所有这些,您可能最好使用数据绑定,并将元素的可见性绑定到视图模型的属性,而不是尝试通过编程来操纵模板。