使用来自不同程序集的资源和DataTemplateSelector [英] Using a resource and DataTemplateSelector from a different assembly

查看:77
本文介绍了使用来自不同程序集的资源和DataTemplateSelector的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在基础程序集中有一个控件,该控件要根据当前DataContext设置内容。

I have a control in a base assembly with Content that I would like to set based on the current DataContext.

为此,我尝试使用资源和调用程序集中的子类DataTemplateSelector,如下所示。我最初的希望是可以调用子类DataTemplateSelector,但不是。然后,我尝试在调用程序集的资源字典中添加一个条目,该条目具有相同的键,但带有子分类的选择器,但这也无法完成。

To do so, I am trying to use a resource and subclassed DataTemplateSelector in the calling assembly as shown below. My initial hope was that the sub classed DataTemplateSelector would be called, but it isn't. Then I tried adding an entry in the Resource Dictionary of the calling assembly with the same key but the sub classed selector, but that doesn't get it done either.

有没有一种方法可以解决我必须完成的代码?有没有更好的策略来设置我在呼叫程序集中的内容?

Is there a way to fix the code I have to make this work? Is there a better strategy to set my content from the calling assembly?

干杯,

Berryl

Cheers,
Berryl

<UserControl 
    ...

    <Grid>
        <Border Style="{StaticResource FilterPanelBorderStyle}">
            <StackPanel Orientation="Horizontal" x:Name="myFilterPanel" >

      *****     <ContentControl x:Name="ctrlFilters" ContentTemplateSelector="{StaticResource filterControlsTemplateSelector}" /> ****

                <Button x:Name="btnClearFilter" Style="{StaticResource FilterPanelClearButtonStyle}" />
                <Label x:Name="lblStatus" Style="{StaticResource FilterPanelLabelStyle}" Content="{Binding Status}" />

            </StackPanel>
        </Border>

    </Grid>
</UserControl>



资源和DataTemplateSelector(基本程序集)



Resources and DataTemplateSelector (base assembly)

<views:FilterControlsTemplateSelector x:Key="filterControlsTemplateSelector"/>

<DataTemplate x:Key="defaultFilterContent">
    <TextBlock>Replace ME with real filters!</TextBlock>
</DataTemplate>

    public class FilterControlsTemplateSelector : DataTemplateSelector
{
    public override DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        var fe = container as FrameworkElement;
        if (fe == null) return null;

        return _GetDataTemplate(fe);
    }

    protected virtual DataTemplate _GetDataTemplate(FrameworkElement fe) {
        var template = fe.FindResource("defaultFilterContent") as DataTemplate;
        return template;
    }
}



资源和选择器(调用程序集)



Resources and Selector (calling Assembly)

<ResourceDictionary.MergedDictionaries>
    <ResourceDictionary Source="pack://application:,,,/Core.Presentation.Wpf;component/Themes/Generic.xaml" />
</ResourceDictionary.MergedDictionaries>

<local:PimFilterControlsTemplateSelector x:Key="filterControlsTemplateSelector"/>

<DataTemplate x:Key="pimFilterContent">
    <Grid>
        <Border Style="{StaticResource FilterPanelBorderStyle}">
            <StackPanel Orientation="Horizontal" >
                <cc:SearchTextBox 
                        x:Name="stbLastNameFilter" Style="{StaticResource FilterPanelSearchTextBoxStyle}"
                        />
                <cc:SearchTextBox 
                        x:Name="stbFirstNameFilter" Style="{StaticResource FilterPanelSearchTextBoxStyle}"
                        />
            </StackPanel>
        </Border>

    </Grid>
</DataTemplate>


public class PimFilterControlsTemplateSelector : FilterControlsTemplateSelector
{

    protected override DataTemplate _GetDataTemplate(FrameworkElement fe)
    {
        var dc = fe.DataContext;
        if (dc == null) return null;

        DataTemplate result = null;
        if (dc is PimMasterVm)
        {
            result = fe.FindResource("pimFilterContent") as DataTemplate;
        }
        else {
            result = base._GetDataTemplate(fe);
        }
        return result;
    }

}



应用程序词典设置(调用程序集)



Application Dictionary setup (calling assembly)

    <Application.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="pack://application:,,,/Parties.Presentation.Wpf;component/PimCommonResources.xaml" />                
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>

</Application.Resources>


推荐答案

我放弃了让DataTemplateSelector工作并结束工作执行以下操作:

I gave up on making the DataTemplateSelector work and wound up doing the following:


  1. 创建FilterContentConverter

  2. 向我的视图模型添加FilterContentKey(字符串)

转换器仅获取FilterContentKey并进行资源查找以获取具有该键的DataTemplate。结束时,它可以很好地测试,甚至更好-它可以工作!

The converter just takes the FilterContentKey and does a resource lookup to get the DataTemplate with that key. This winds up being nicely testable, and even better - it works!

下面的解决方案代码,这要感谢弗拉达米尔·多罗霍夫(Vladamir Dorokhov)以及该SO答案是为了帮助我正确设置ContentControl绑定。

Solution code below, with thanks to Vladamir Dorokhov and this SO answer for helping me get the ContentControl binding right.

HTH,

Berryl

HTH,
Berryl

<Grid>
    <Border Style="{StaticResource FilterPanelBorderStyle}">
        <StackPanel Orientation="Horizontal" x:Name="myFilterPanel" >
            <ContentControl x:Name="ctrlFilters" 
                            ContentTemplate="{Binding Path=FilterContentKey, Converter={StaticResource filterTemplateContentConv}}" />
            <Button x:Name="btnClearFilter" Style="{StaticResource FilterPanelClearButtonStyle}" />
            <Label x:Name="lblStatus" Style="{StaticResource FilterPanelLabelStyle}" Content="{Binding Status}" />

        </StackPanel>
    </Border>

</Grid>

<DataTemplate x:Key="pimFilterContent">
    <StackPanel Orientation="Horizontal" >
        <cc:SearchTextBox x:Name="stbLastNameFilter" 
            Style="{StaticResource FilterPanelSearchTextBoxStyle}"
            Text="{Binding Path=LastNameFilter, UpdateSourceTrigger=PropertyChanged}" 
                        />
        <cc:SearchTextBox x:Name="stbFirstNameFilter" 
            Style="{StaticResource FilterPanelSearchTextBoxStyle}"
            Text="{Binding Path=FirstNameFilter, UpdateSourceTrigger=PropertyChanged}" 
                        />
    </StackPanel>
</DataTemplate>



转换器



Converter

/// <summary>
/// Thin wrapper around a resource lookup designed to result in a <see cref="DataTemplate"/> 
/// representing filering controls.
/// </summary>
[ValueConversion(typeof(object), typeof(DataTemplate))]
public class FilterTemplateContentConverter : IValueConverter
{
    public const string DEFAULT_CONTENT = "undefinedFilterContent";
    protected readonly ResourceLocator _resourceLocator;

    /// <summary>
    /// Initializes a new instance of the <see cref="FilterTemplateContentConverter"/> class.
    /// Unit tests can use this to pass in an app for the <see cref="ResourceLocator"/>.
    /// </summary>
    /// <param name="app">The app.</param>
    public FilterTemplateContentConverter(Application app) { _resourceLocator = new ResourceLocator(app); }

    /// <summary>
    /// Initializes a new instance of the <see cref="FilterTemplateContentConverter"/> class.
    /// The 'real' application uses this.
    /// </summary>
    public FilterTemplateContentConverter()
    {
        _resourceLocator = new ResourceLocator();
    }

    public virtual object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
        var key = value as string;
        return _resourceLocator.GetResource(key ?? DEFAULT_CONTENT);
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); }
}

这篇关于使用来自不同程序集的资源和DataTemplateSelector的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆