繁体   English   中英

在值转换器中选择ItemTemplate

[英]Select ItemTemplate in value converter

我试图在基于每个项目属性的列表视图中有多个ItemTemplates。 但是我在值转换器中不断收到{“对COM组件的调用已返回错误HRESULT E_FAIL。”}:

public class EquipmentTemplateConverter : IValueConverter
{
    public object Convert(object value, Type type, object parameter, string language)
    {
        switch ((EquipmentType) (int) value)
        {
            case EquipmentType.Normal:
                return Application.Current.Resources.FirstOrDefault(r => r.Key.ToString() == "EquipmentNormalTemplate");
            case EquipmentType.Upgrade:
                return Application.Current.Resources.FirstOrDefault(r => r.Key.ToString() == "EquipmentUpgradeTemplate");
            default:
                throw new ArgumentOutOfRangeException(nameof(value), value, null);
        }
    }

    public object ConvertBack(object value, Type type, object parameter, string language)
    {
        throw new NotImplementedException();
    }
}

XAML:

    <DataTemplate x:Key="EquipmentTemplate" >
        <Grid>
            <ContentControl DataContext="{Binding}" Content="{Binding}" x:Name="TheContentControl" ContentTemplate="{Binding Equipment.Type, Converter={StaticResource EquipmentTemplateConverter } }" />
        </Grid>
    </DataTemplate>

有什么想法可以解决这个问题吗?

通常的方法是编写一个DataTemplateSelector并将其实例分配给ContentControl.ContentTemplateSelector

<DataTemplate x:Key="EquipmentTemplate" >
    <DataTemplate.Resources>
        <local:EquipmentTemplateSelector x:Key="EquipmentTemplateSelector" />
    </DataTemplate.Resources>
    <Grid>
        <ContentControl 
            DataContext="{Binding}" 
            Content="{Binding}" 
            x:Name="TheContentControl" 
            ContentTemplateSelector="{StaticResource EquipmentTemplateSelector}" 
            />
    </Grid>
</DataTemplate>

C#:

public class EquipmentTemplateSelector : DataTemplateSelector
{
    public override DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        //  container is the container. Cast it to something you can call
        //  FindResource() on. Put in a breakpoint and use the watch window. 
        //  I'm at work with Windows 7. Shouldn't be too hard.
        var whatever = container as SomethingOrOther;

        Object resKey = null;

        //  ************************************
        //  Do stuff here to pick a resource key
        //  ************************************

        //  Application.Current.Resources is ONE resource dictionary.
        //  Use FindResource to find any resource in scope. 
        return whatever.FindResource(resKey) as DataTemplate;
    }
}

但是我在值转换器中不断收到{“对COM组件的调用已返回错误HRESULT E_FAIL。”}。

当对样式或事件处理程序的引用不存在或不在XAML上下文中时,通常会发生此错误。

您仅发布了转换器的代码和xaml代码的一部分,我无法100%复制数据模型和xaml,但是从您的代码中,我认为在转换器中,您想返回特定的DataTemplate ,但是您实际上返回了一个KeyValuePair<object, object> ,资源在ResourceDictionary中定义,并遵循“键值”部分,有关更多信息,您可以参考ResourceDictionary和XAML资源引用

在这里,我写了一个示例,再次我没有100%复制您的xaml和数据模型:

MainPage.xaml:

<Page.Resources>
    <local:EquipmentTemplateConverter x:Key="EquipmentTemplateConverter" />
</Page.Resources>

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <ListView ItemsSource="{x:Bind list}">
        <ListView.ItemTemplate>
            <DataTemplate>
                <ContentControl DataContext="{Binding}" Content="{Binding}" ContentTemplate="{Binding Count, Converter={StaticResource EquipmentTemplateConverter}}" />
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</Grid>

后面的代码:

private ObservableCollection<EquipmentType> list = new ObservableCollection<EquipmentType>();

public MainPage()
{
    this.InitializeComponent();
}

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    list.Add(new EquipmentType { Count = 0 });
    list.Add(new EquipmentType { Count = 1 });
    list.Add(new EquipmentType { Count = 0 });
    list.Add(new EquipmentType { Count = 0 });
    list.Add(new EquipmentType { Count = 1 });
    list.Add(new EquipmentType { Count = 1 });
}

我的EquipmentType类非常简单:

public class EquipmentType
{
    public int Count { get; set; }
}

EquipmentTemplateConverter是这样的:

public class EquipmentTemplateConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, string language)
    {
        switch ((int)value)
        {
            case 0:
                var a = Application.Current.Resources.FirstOrDefault(r => r.Key.ToString() == "EquipmentNormalTemplate");
                return a.Value;

            case 1:
                var b = Application.Current.Resources.FirstOrDefault(r => r.Key.ToString() == "EquipmentUpgradeTemplate");
                return b.Value;

            default:
                throw new ArgumentOutOfRangeException(nameof(value), value, null);
        }
    }

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

由于您在转换器中使用Application.Resources属性 ,因此我只将DataTemplate放在App.xaml中进行测试:

<Application.Resources>
    <DataTemplate x:Key="EquipmentNormalTemplate">
        <Grid>
            <TextBlock Text="This is EquipmentNormalTemplate." />
        </Grid>
    </DataTemplate>
    <DataTemplate x:Key="EquipmentUpgradeTemplate">
        <Grid>
            <TextBlock Text="This is EquipmentUpgradeTemplate." />
        </Grid>
    </DataTemplate>
</Application.Resources>

但是我同意@Ed Plunkett的观点,使用DataTemplateSelector是完成这项工作的更常见方法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM