2012-04-18 6 views
0

ListView内の複数の列に対してDataTemplateを再利用したい。与えられた2つのXmlDataProviderは、最初の項目で選択した項目を使用して2番目の値から値を選択します。 DataTemplateに追加リソースを指定すると、これが機能します。しかし、これは私にDataTemplateのコードを複製させ、追加のリソースを交換するように強制します。 私は何をしたいのはこれです:XAMLコードの上に次のエラーが仕事と生成しないこと複数のリソースをDataTemplateに渡すことはできますか?

public class MultiXmlConverter : IMultiValueConverter 
    { 
    public object Convert(object[] value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     var element = value[0] as XmlElement; 
     var dataProvider = value[1] as XmlDataProvider; 
     XmlNodeList nodes = dataProvider.Document.SelectNodes("/Items/Item/[@id='" + element.Attributes["id"].Value.ToString() + "']"); 
     return nodes[0].Attributes["Text"].Value.ToString(); 
    } 
    public object[] ConvertBack(object value, Type[] targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     throw new Exception("The method or operation is not implemented."); 
    } 
    } 

注:ここでは、完全(および参照)のために

<Window x:Class="LayoutTests.Window2" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:local="clr-namespace:LayoutTests" 
     Title="Window2" Height="300" Width="300"> 
    <Window.Resources> 
    <XmlDataProvider x:Key="XmlDataA" IsInitialLoadEnabled="True"> 
     <x:XData> 
     <Items xmlns=""> 
      <Item id="1" text="A:1"/> 
      <Item id="2" text="A:2"/> 
      <Item id="3" text="A:3"/> 
     </Items> 
     </x:XData> 
    </XmlDataProvider> 
    <XmlDataProvider x:Key="XmlDataB" IsInitialLoadEnabled="True"> 
     <x:XData> 
     <Items xmlns=""> 
      <Item id="1" text="B:1"/> 
      <Item id="2" text="B:2"/> 
      <Item id="3" text="B:3"/> 
     </Items> 
     </x:XData> 
    </XmlDataProvider> 
    <local:MultiXmlConverter x:Key="MultiXmlConverter"/> 
    <local:DatabindingDebugConverter x:Key="DatabindingDebugConverter"/> 
    <DataTemplate x:Key="Template" > 
     <TextBlock Text="{Binding Converter={StaticResource MultiXmlConverter}}"/> 
    </DataTemplate> 
    </Window.Resources> 
    <Grid> 
    <ListView ItemsSource="{Binding Source={StaticResource XmlDataA}, XPath='/Items/Item'}" Background="Transparent"> 
     <ListView.View> 
     <GridView> 
      <GridViewColumn CellTemplate="{StaticResource Template}"> 
      <GridViewColumn.DisplayMemberBinding> 
       <MultiBinding> 
       <Binding Path="/"/> 
       <Binding Source="{StaticResource XmlDataB}"/> 
       </MultiBinding> 
      </GridViewColumn.DisplayMemberBinding> 
      </GridViewColumn> 
     </GridView> 
     </ListView.View> 
    </ListView> 
    </Grid> 
</Window> 

が可能コンバータです。 "MultiValueConverterを指定する必要があるため、MultiBindingを設定できません。" MultiBindingは、私がやりたいことの単なるプレースホルダーです。研究は、DataTemplateに追加のパラメータを渡す可能性を明らかにしていませんでした - しかし、私はそれほど有用な何かがどこかに隠されていないと信じていません。

の横にあるDataTemplateに追加リソースを渡すにはどうすればよいですか?

+0

何らかの関連する質問はhttp://stackoverflow.com/questions/8328443/generic-datatemplate-used-in-multiple-gridviewcolumnsです。 – Pascal

答えて

0

多くのデバッグとディスカッションの後、私は上記の問題に対する解決策を見つけました。 追加のデータをテンプレートに渡すには、階層内の親要素にプロパティをアタッチします。残念ながら、私たちがアクセスしているもの - GridViewColumnはビジュアルツリーに表示されていません。適切なリソースを指定できるようにするには、少し上にまとめていく必要があります。私は、これは少し長いです完全であることを上記の例変更:

<Window x:Class="LayoutTests.Window2" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:local="clr-namespace:LayoutTests" 
     Title="Window2" Height="300" Width="300"> 
    <Window.Resources> 
    <ResourceDictionary> 
     <ResourceDictionary.MergedDictionaries> 
     <ResourceDictionary> 
      <XmlDataProvider x:Key="XmlDataA" IsInitialLoadEnabled="True"> 
      <x:XData> 
       <Items xmlns=""> 
       <Item id="1" text="A:1"/> 
       <Item id="2" text="A:2"/> 
       <Item id="3" text="A:3"/> 
       </Items> 
      </x:XData> 
      </XmlDataProvider> 
     </ResourceDictionary> 
     <ResourceDictionary> 
      <XmlDataProvider x:Key="XmlDataB" IsInitialLoadEnabled="True"> 
      <x:XData> 
       <Items xmlns=""> 
       <Item id="1" text="B:1"/> 
       <Item id="2" text="B:2"/> 
       <Item id="3" text="B:3"/> 
       </Items> 
      </x:XData> 
      </XmlDataProvider> 
     </ResourceDictionary> 
     <ResourceDictionary> 
      <local:MultiXmlConverter x:Key="MultiXmlConverter"/> 
      <local:DatabindingDebugConverter x:Key="DatabindingDebugConverter"/> 
      <DataTemplate x:Key="Template" > 
      <TextBlock> 
       <TextBlock.Text> 
       <MultiBinding Converter="{StaticResource MultiXmlConverter}"> 
        <Binding/> 
        <Binding RelativeSource="{RelativeSource TemplatedParent}" Path="(local:Window2.AttachedXmlDataProvider)"/> 
       </MultiBinding> 
       </TextBlock.Text> 
      </TextBlock> 
      </DataTemplate> 
      <DataTemplate x:Key="TemplateA"> 
      <ContentPresenter ContentTemplate="{StaticResource Template}" local:Window2.AttachedXmlDataProvider="{StaticResource XmlDataA}"/> 
      </DataTemplate> 
      <DataTemplate x:Key="TemplateB"> 
      <ContentPresenter ContentTemplate="{StaticResource Template}" local:Window2.AttachedXmlDataProvider="{StaticResource XmlDataB}"/> 
      </DataTemplate> 
     </ResourceDictionary> 
     </ResourceDictionary.MergedDictionaries> 
    </ResourceDictionary> 
    </Window.Resources> 
    <Grid> 
    <ListView ItemsSource="{Binding Source={StaticResource XmlDataA}, XPath='/Items/Item'}" Background="Transparent"> 
     <ListView.View> 
     <GridView> 
      <GridViewColumn CellTemplate="{StaticResource TemplateA}"/> 
      <GridViewColumn CellTemplate="{StaticResource TemplateB}"/> 
     </GridView> 
     </ListView.View> 
    </ListView> 
    </Grid> 
</Window> 

とは.csファイルからのもの:

public partial class Window2 : Window 
    { 
    public Window2() 
    { 
     InitializeComponent(); 
    } 

    public static readonly DependencyProperty AttachedXmlDataProviderProperty = 
    DependencyProperty.RegisterAttached("AttachedXmlDataProvider", 
             typeof(XmlDataProvider), 
             typeof(Window2), 
             new FrameworkPropertyMetadata((XmlDataProvider)null, FrameworkPropertyMetadataOptions.AffectsRender)); 
    public static void SetAttachedXmlDataProvider(DependencyObject depObj, XmlDataProvider value) 
    { 
     depObj.SetValue(AttachedXmlDataProviderProperty, value); 
    } 
    public static XmlDataProvider GetAttachedXmlDataProvider(DependencyObject depObj) 
    { 
     return (XmlDataProvider)depObj.GetValue(AttachedXmlDataProviderProperty); 
    } 
    } 

    public class MultiXmlConverter : IMultiValueConverter 
    { 
    public object Convert(object[] value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     var element = value[0] as XmlElement; 
     var dataProvider = value[1] as XmlDataProvider; 
     string id = element.Attributes["id"].Value.ToString(); 
     if(dataProvider.Document == null) 
     return null; 
     XmlNodeList nodes = dataProvider.Document.SelectNodes("/Items/Item[@id='" + id + "']"); 
     string result = nodes[0].Attributes["text"].Value; 
     return result; 
    } 
    public object[] ConvertBack(object value, Type[] targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     throw new Exception("The method or operation is not implemented."); 
    } 
    } 

コードの美しさは、上記事実にあるものたち別のリソースをDataTemplateに統合し、少量のコードでリソースを交換することができます。つまり、DataTemplateを書くだけで、実際のテンプレートを単純にまとめます。 上記の例では明らかではないかもしれませんが、実際に複雑なものがある場合は、DataTemplateとなり、リソースを変更するだけで済むようになりました。

関連する問題