none
ListViewをデータの内容に応じて表示を切り替える方法 RRS feed

  • 質問

  •  

    ListViewの中に配置しているTextBlockにおいて、TextBlockの内容に応じて表示・非表示を動的に切り替える方法はありますでしょうか?

     

    TextBlockの「NameKanji」にデータが入っていない場合は Name="NameKanji"を非表示に、データが入っている場合はName="NameAnk"を非表示へと、データの内容に応じて切り替えたいのです。

    (漢字データを優先的に表示させる)

     

    <DataTemplate x:Key="ItemTemplate1">
        <StackPanel>
            <TextBlock Name="NameAnk" FontSize="16" Text="{Binding Path=NameAnk}" />
            <TextBlock Name="NameKanji" FontSize="16" Text="{Binding Path=NameKanji}" />
        </StackPanel>
    </DataTemplate>

    ---中略---

     

    <ListView Name="lvwList">
        <ListView.View>
            <GridView>
                <GridViewColumn Header="名前" CellTemplate="{StaticResource ItemTemplate1}" />
            </GridView>
        </ListView.View>
    </ListView>

     

     

    ASP.NETのGridViewであればRowDataBoundイベントにより、行へのデータ接続時にコントロールの中身を確認した上で、表示・非表示を切り替えることが出来ましたが、WPFのListViewでは行へのデータ接続時のイベントも見当たりません。(自分が知らないだけかもしれませんが。。。)

    2008年12月12日 11:18

回答

  •         <Converters:VisibilityConverter x:Key="visibilityConverter" />
            <DataTemplate x:Key="itemTemplate">
                <StackPanel>
                    <TextBlock FontSize="16px" Text="{Binding NameAnk}" />
                    <TextBlock FontSize="16px" Text="{Binding NameKanji}" Visibility="{Binding NameKanji, Converter={StaticResource visibilityConverter}}"/>
                </StackPanel>
            </DataTemplate>

     

    ----------------------------------------------------------------

        public class VisibilityConverter : IValueConverter
        {
            public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
            {
                var text = value is string ? (string) value : string.Empty;
                return string.IsNullOrEmpty(text) ? Visibility.Collapsed : Visibility.Visible;
            }

     

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

     

    こんな感じでどうでしょうか?

     

    ======================================================================

    追記)

    DataTemplateSelectorを使った場合の例も紹介しておきます。

    ただし、変更通知の関係で期待するだけの動きをするかどうか多少不安があります。

     

        <Window.Resources>
            <Selector:TextTemplateSelector x:Key="textTemplateSelector" />
            <DataTemplate x:Key="itemTemplate1">
                <StackPanel>
                    <TextBlock FontSize="16px" Text="{Binding NameKanji}"/>
                </StackPanel>
            </DataTemplate>
            <DataTemplate x:Key="itemTemplate2">
                <StackPanel>
                    <TextBlock FontSize="16px" Text="{Binding NameAnk}"/>
                </StackPanel>
            </DataTemplate>
        </Window.Resources>

    -------------------------------------------------

        class TextTemplateSelector : DataTemplateSelector
        {
            public override DataTemplate SelectTemplate(object item, DependencyObject container)
            {
                PropertyInfo info = item.GetType().GetProperty("NameKanji");
                if (info == null)
                    return null;
                string nameKanji = GetText(info, item);
                var element = (FrameworkElement)container;
                if (!string.IsNullOrEmpty(nameKanji))
                    return (DataTemplate)element.FindResource("itemTemplate1");
                return (DataTemplate)element.FindResource("itemTemplate2");
            }

            private static string GetText(PropertyInfo info, object instance)
            {
                object value = info.GetValue(instance, null);
                return value is string ? (string) value : string.Empty;
            }
        }

     

     

    2008年12月13日 3:06
  • 丁寧なサンプルコードをつけて頂きありがとうございます。

     

    さっそく試してみたところ、どちらのパターンにおいても、期待どおりの動きをしているようです。

    個人的には [DataTemplateSelector] を使った場合の方が、汎用性が高くいろいろな用途に使えそうだと感じています。

     

    WPFに関してはまだまだWEB上にも情報が少なく、また従来のWindowsFormのコーディングから大幅に変わってしまっているので正直かなりてこずっています。

    ありがとうございました。

    2008年12月15日 2:47

すべての返信

  •         <Converters:VisibilityConverter x:Key="visibilityConverter" />
            <DataTemplate x:Key="itemTemplate">
                <StackPanel>
                    <TextBlock FontSize="16px" Text="{Binding NameAnk}" />
                    <TextBlock FontSize="16px" Text="{Binding NameKanji}" Visibility="{Binding NameKanji, Converter={StaticResource visibilityConverter}}"/>
                </StackPanel>
            </DataTemplate>

     

    ----------------------------------------------------------------

        public class VisibilityConverter : IValueConverter
        {
            public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
            {
                var text = value is string ? (string) value : string.Empty;
                return string.IsNullOrEmpty(text) ? Visibility.Collapsed : Visibility.Visible;
            }

     

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

     

    こんな感じでどうでしょうか?

     

    ======================================================================

    追記)

    DataTemplateSelectorを使った場合の例も紹介しておきます。

    ただし、変更通知の関係で期待するだけの動きをするかどうか多少不安があります。

     

        <Window.Resources>
            <Selector:TextTemplateSelector x:Key="textTemplateSelector" />
            <DataTemplate x:Key="itemTemplate1">
                <StackPanel>
                    <TextBlock FontSize="16px" Text="{Binding NameKanji}"/>
                </StackPanel>
            </DataTemplate>
            <DataTemplate x:Key="itemTemplate2">
                <StackPanel>
                    <TextBlock FontSize="16px" Text="{Binding NameAnk}"/>
                </StackPanel>
            </DataTemplate>
        </Window.Resources>

    -------------------------------------------------

        class TextTemplateSelector : DataTemplateSelector
        {
            public override DataTemplate SelectTemplate(object item, DependencyObject container)
            {
                PropertyInfo info = item.GetType().GetProperty("NameKanji");
                if (info == null)
                    return null;
                string nameKanji = GetText(info, item);
                var element = (FrameworkElement)container;
                if (!string.IsNullOrEmpty(nameKanji))
                    return (DataTemplate)element.FindResource("itemTemplate1");
                return (DataTemplate)element.FindResource("itemTemplate2");
            }

            private static string GetText(PropertyInfo info, object instance)
            {
                object value = info.GetValue(instance, null);
                return value is string ? (string) value : string.Empty;
            }
        }

     

     

    2008年12月13日 3:06
  • 丁寧なサンプルコードをつけて頂きありがとうございます。

     

    さっそく試してみたところ、どちらのパターンにおいても、期待どおりの動きをしているようです。

    個人的には [DataTemplateSelector] を使った場合の方が、汎用性が高くいろいろな用途に使えそうだと感じています。

     

    WPFに関してはまだまだWEB上にも情報が少なく、また従来のWindowsFormのコーディングから大幅に変わってしまっているので正直かなりてこずっています。

    ありがとうございました。

    2008年12月15日 2:47