如何在WPF中的DataTemplateSelector类中从UserControl中查找资源?

5

我正在创建自己的UserControl,而且在我的XAML中,在UserControl.Resources部分下有两个不同的DataTemplates。我想根据列表视图中显示的对象的属性值选择这两个数据模板之一。我通过创建自定义DataTemplateSelector类并重写SelectTemplate方法来实现此目的,该方法应返回我希望使用的DataTemplate。然而,我不知道如何“找到”位于UserControls资源部分中的datatemplates,我看到的所有示例都只从Window.Resources中获取datatemplates。在这个示例中,他们获取当前的MainWindow,然后使用FindResource查找DataTemplate,那么我该如何以类似的方式获取我的UserControl呢?


public override DataTemplate 
            SelectTemplate(object item, DependencyObject container)
        {
            if (item != null && item is AuctionItem)
            {
                AuctionItem auctionItem = item as AuctionItem;
                Window window = Application.Current.MainWindow;

                switch (auctionItem.SpecialFeatures)
                {
                    case SpecialFeatures.None:
                        return 
                            window.FindResource("AuctionItem_None") 
                            as DataTemplate;
                    case SpecialFeatures.Color:
                        return 
                            window.FindResource("AuctionItem_Color") 
                            as DataTemplate;
                }
            }

            return null;
        }

上面的示例来自于这里:ItemsControl.ItemTemplateSelector 属性

4个回答

8

试试这个:

    public override DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        if (item != null && item is AuctionItem)
        {
            AuctionItem auctionItem = item as AuctionItem;

            switch (auctionItem.SpecialFeatures)
            {
                case SpecialFeatures.None:
                    return 
                        ((FrameworkElement)container).FindResource("AuctionItem_None") 
                        as DataTemplate;
                case SpecialFeatures.Color:
                    return 
                        ((FrameworkElement)container).FindResource("AuctionItem_Color") 
                        as DataTemplate;
            }
        }

        return null;
    }

8

我通常会在代码后台实例化DataTemplateSelector,并将UserControl作为构造函数中的参数传递,如下所示:

public class MyUserControl : UserControl
{
    public MyUserControl()
    {
        Resources["MyDataTemplateSelector"] = new MyDataTemplateSelector(this);
        InitializeComponent();
    }
}

public class MyDataTemplateSelector : DataTemplateSelector
{
    private MyUserControl parent;
    public MyDataTemplateSelector(MyUserControl parent)
    {
        this.parent = parent;
    }

    public override DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        parent.DoStuff();
    }
}

虽然不是城里最漂亮的女孩,但它能够完成工作 ;)

希望这可以帮到您!


1
在XAML中没有相同的方法吗? - Joakim
好的,这个可以正常工作... 但最好知道推荐的做法,最好在XAML中完成所有操作。 - Joakim
非常正确。我也想知道更好的方法,但实际上我不认为可以用XAML解决这个问题。你需要在代码后台中引用某种方式,所以最简单的方法就是直接给出;) - Arcturus
这似乎是在Metro中完成此任务的唯一方法。由于Metro的实现限制,其他选项都无法使用。 - SergioL
这会创建一个保留循环吗? - Vasiliy Kulakov

2
       <DataTemplate x:Key="addTemplate">
        <Button Command="{Binding Path=AddCommand}">Add</Button>
    </DataTemplate>

    <DataTemplate x:Key="editTemplate">
        <Button Command="{Binding Path=UpdateCommand}">Update</Button>
    </DataTemplate>

    <TemplateSelectors:AddEditTemplateSelector
        AddTemplate="{StaticResource addTemplate}"
        EditTemplate="{StaticResource editTemplate}"
        x:Key="addEditTemplateSelector" />

仅限使用XAML!


0
一个WinRT和Windows Phone的解决方案涉及到沿着可视化树向上移动,直到找到父控件为止:
    protected override Windows.UI.Xaml.DataTemplate SelectTemplateCore(object item, Windows.UI.Xaml.DependencyObject container)
    {
        var parent = FindParent<MyParentControlType>(container as FrameworkElement);

        if(parent != null)
        {
            if (item is Something)
                return parent.Resources["TemplateForSomething"] as DataTemplate;
            else if(item is SomethingElse)
                return parent.Resources["TemplateForSomethingElse"] as DataTemplate;
            else 
                // etc
        }
        else
        {
            return App.Current.Resources["SomeFallbackResource"] as DataTemplate;
        }
    }

    public static T FindParent<T>(FrameworkElement element) where T : FrameworkElement
    {
        FrameworkElement parent = Windows.UI.Xaml.Media.VisualTreeHelper.GetParent(element) as FrameworkElement;

        while (parent != null)
        {
            T correctlyTyped = parent as T;

            if (correctlyTyped != null)
                return correctlyTyped;
            else
                return FindParent<T>(parent);
        }

        return null;
    }

FindParent方法基于这里的被接受的答案:如何从ListViewItem获取ListView?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接