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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/916012/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 03:07:58  来源:igfitidea点击:

How to find a resource in a UserControl from a DataTemplateSelector class in WPF?

c#.netwpfresourceswpf-controls

提问by Joakim

I'm creating my own UserControl and I have two different DataTemplates under the UserControl.Resourcessection in my XAML. I want to choose between these two datatemplates depending on the value of a property on objects displayed in a listview. I do this by creating a custom DataTemplateSelectorclass and overriding the SelectTemplatemethod which is supposed to return the DataTemplate I wish to use. However, I have no idea how to "find" my datatemplates that are located in the UserControls resource section, all the examples I've seen only fetches datatemplates from Window.Resources. In this example they fetch the current MainWindowand then use FindResourceto find the DataTemplate, how do I fetch my UserControlin a similar manner?:

我正在创建自己的 UserControl,并且在 XAML的UserControl.Resources部分下有两个不同的 DataTemplates 。我想根据列表视图中显示的对象的属性值在这两个数据模板之间进行选择。为此,我创建了一个自定义DataTemplateSelector类并覆盖了应该返回我希望使用的 DataTemplate的SelectTemplate方法。但是,我不知道如何“查找”位于 UserControls 资源部分中的数据模板,我看到的所有示例都只从Window.Resources获取数据模板。在这个例子中,他们获取当前的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;
        }

The example above is from here: ItemsControl.ItemTemplateSelector Property

上面的例子来自这里:ItemsControl.ItemTemplateSelector Property

采纳答案by Arcturus

I usually instantiate my DataTemplateSelector from code behind with the UserControl as parameter in the constructor of the DataTemplateSelector, like so:

我通常使用 UserControl 作为 DataTemplateSelector 构造函数中的参数从后面的代码实例化我的 DataTemplateSelector,如下所示:

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();
    }
}

Not the most prettiest girl in town, but it get the job done ;)

不是镇上最漂亮的女孩,但它完成了工作;)

Hope this helps!

希望这可以帮助!

回答by msfanboy

       <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 only!

仅限 XAML!

回答by scrat789

Try this:

尝试这个:

    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;
    }

回答by Vasiliy Kulakov

A WinRT & Windows Phone solution involves moving up the visual tree until the parent control is found:

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;
    }

The FindParent method is based on the accepted answer here: How to get a ListView from a ListViewItem?

FindParent 方法基于此处接受的答案:How to get a ListView from a ListViewItem?