2016-05-19 1 views
-1

各アイテムプロパティに基づいてリストビュー内に複数のItemTemplatesを作成しようとしています。値のコンバーターでItemTemplateを選択

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> 

任意のアイデア私はこの問題を解決する方法をしかし、私は{「エラーHRESULT E_FAILがCOMコンポーネントへの呼び出しから返されました」}取得私の価値コンバータに保ちます?

答えて

1

これを行う通常の方法は、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; 
    } 
} 
+0

私はWindowsアプリケーションを作成しているので、私はApplication.CurrentにMainWindowプロパティを持っていません。 – shady

+0

@shady更新しました。 –

0

しかし、私は{ "エラーHRESULT E_FAILがCOMコンポーネントへの呼び出しから返されました。"}ばかりの私値変換してください。

このエラーは、通常、存在しないか、XAMLのコンテキスト内にないスタイルまたはイベントハンドラへの参照が発生した場合に発生します。

あなたのコンバーターのコードとxamlコードの一部だけを投稿しましたが、データモデルとxamlを100%再生できませんが、コードからはコンバーターで具体的にはDataTemplateですが、実際にはKeyValuePair<object, object>が返され、リソースはResourceDictionaryに定義されています。詳しくは、ResourceDictionary and XAML resource referencesを参照してください。

ここで私は、私は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 propertyを使用しているので、私はテストのためにApp.xamlでDataTemplateを置く:

<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を使用してこの作業を行う一般的な方法です。

関連する問題