【问题标题】:Using a resource and DataTemplateSelector from a different assembly使用来自不同程序集的资源和 DataTemplateSelector
【发布时间】:2011-09-18 13:55:05
【问题描述】:

我在基础程序集中有一个控件,其中包含我想根据当前 DataContext 设置的内容。

为此,我尝试在调用程序集中使用资源和子类 DataTemplateSelector,如下所示。我最初的希望是调用子类 DataTemplateSelector,但事实并非如此。然后我尝试在调用程序集的资源字典中添加一个条目,使用相同的键但子类选择器,但这也没有完成。

有没有办法修复我必须使它工作的代码?有没有更好的策略来从调用程序集中设置我的内容?

干杯,
浆果

用户控件(基础程序集)

<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(基础程序集)

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

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

<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.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="pack://application:,,,/Parties.Presentation.Wpf;component/PimCommonResources.xaml" />                
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>

</Application.Resources>

【问题讨论】:

    标签: wpf datatemplate resourcedictionary contentcontrol


    【解决方案1】:

    我放弃了让 DataTemplateSelector 工作并最终做了以下事情:

    1. 创建 FilterContentConverter
    2. 将 FilterContentKey(字符串)添加到我的视图模型中

    转换器只需使用 FilterContentKey 并进行资源查找以获取具有该键的 DataTemplate。这最终可以很好地测试,甚至更好 - 它有效!

    下面的解决方案代码,感谢Vladamir Dorokhov and this SO answer 帮助我获得了 ContentControl 绑定权。

    HTH,
    浆果

    过滤控制

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

    转换器

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-03
      • 1970-01-01
      • 2021-08-26
      • 1970-01-01
      相关资源
      最近更新 更多