泥庭

2011年1月17日

ListViewあれこれ

Filed under: .NET, WPF — タグ: , — yone64 @ 10:05 午後

その1、ListViewでやっちゃいけないこと

「等価と判断されるオブジェクトを複数含むListとBind」
いきなり言ってもなんのこっちゃなので、とりあえずコードをば

<XAML>

<Window x:Class="WpfApplication9.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="342" Loaded="Window_Loaded">
    <Grid>
        <ListView Name="listView1" ItemsSource="{Binding}">
            <ListView.View>
                <GridView>
                    <GridViewColumn Header="へっだ" DisplayMemberBinding="{Binding}"/>
                </GridView>
            </ListView.View>
        </ListView>
    </Grid>
</Window>

<C#>

namespace WpfApplication9
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            this.DataContext = new[]
            {
                "AAA","BBB","CCC","DDD","AAA","BBB","CCC","DDD","AAA","BBB","CCC","DDD",
            };
        }
    }
}

長く見えるけど、ListViewを配置してDataContextにstringの配列を突っ込んでるだけです。

ポイントは、同じ文字列が繰り返し出てくること。後は実行して、適当に選択するとあら不思議。

その2、SelectedItemsとバインド

ListViewのSelectedItemsとは、バインド出来ません。困ったw。

なので、ListViewItemのIsSelectedプロパティとListView.ItemsSourceに含まれるオブジェクトの任意のプロパティーをBindします。

とはいえ、ListViewItemはxaml上には登場してません。ということで、Styleを使用することになります。

<ListView.ItemContainerStyle>
    <Style TargetType="{x:Type ListViewItem}">
        <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
    </Style>
</ListView.ItemContainerStyle>

その3、Contextメニューが表示されたアイテムを取得する

ListViewに表示されているどの項目で右クリックされたか知りたい場合があります。

そんな場合は、ContextMenu.PlacementTargetプロパティをCommandParameterに渡せばOK。

<ListView Name="listView1" ItemsSource="{Binding}">
    <ListView.Resources>
        <ContextMenu x:Key="menu">
            <MenuItem Header="メニュー" Command="{Binding HogeCommand}" 
                      CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=ContextMenu}, Path=PlacementTarget.Content}"/>
        </ContextMenu>
    </ListView.Resources>
    <ListView.ItemContainerStyle>
        <Style TargetType="{x:Type ListViewItem}">
            <Setter Property="ContextMenu" Value="{StaticResource ResourceKey=menu}"/>
        </Style>
    </ListView.ItemContainerStyle>
    <ListView.View>
        <GridView>
            <GridViewColumn Header="へっだ" DisplayMemberBinding="{Binding}"/>
        </GridView>
    </ListView.View>
</ListView>

後にいくほど適当だな。。。

2010年11月7日

ListViewのVisualTree

Filed under: WPF — タグ: , , — yone64 @ 3:20 午後

ListViewの動作が気になった(※)ので、ListViewのVisualTreeを確認。
ついでなので、VisualTreeをTreeViewで表示できるようにチャレンジ。

※水平方向にはスクロール同期するが、垂直方向には動かない。

結果、ScrollViewerが入れ子になってた。

XAML

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525" Loaded="Window_Loaded">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="267" />
            <ColumnDefinition Width="236*" />
        </Grid.ColumnDefinitions>
        <ContentControl Name="contentControl1">
            <ListView Name="listView1" ItemsSource="{Binding}">
                <ListView.View>
                    <GridView>
                        <GridViewColumn Header="列1" DisplayMemberBinding="{Binding Path=Name}"/>
                        <GridViewColumn Header="列2" DisplayMemberBinding="{Binding Path=Value}" />
                    </GridView>
                </ListView.View>
            </ListView>
        </ContentControl>
        <TreeView Grid.Column="1" Name="treeView1" ItemsSource="{Binding}">
            <TreeView.ItemTemplate>
                <HierarchicalDataTemplate ItemsSource="{Binding Path=Children}">
                    <TextBlock Text="{Binding Path=DisplayString}" />
                </HierarchicalDataTemplate>
            </TreeView.ItemTemplate>
        </TreeView>
    </Grid>
</Window>

C#

using System.Collections.ObjectModel;
using System.Linq;
using System.Windows;
using System.Windows.Media;

namespace WpfApplication1
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            listView1.DataContext = new[]
            {
                new {Name = "なまえ1", Value = "あたい1"},
                new {Name = "なまえ2", Value = "あたい2"},
                new {Name = "なまえ3", Value = "あたい3"},
                new {Name = "なまえ4", Value = "あたい4"},
            };
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            treeView1.DataContext = Enumerable.Repeat(new VisualTreeItem((DependencyObject)contentControl1.Content), 1);
        }
    }

    public class VisualTreeItem
    {
        private DependencyObject _d;

        public VisualTreeItem(DependencyObject d)
        {
            _d = d;
            int count = VisualTreeHelper.GetChildrenCount(d);
            Children = new ObservableCollection<VisualTreeItem>(
                Enumerable.Range(0, count)
                        .Select(i => new VisualTreeItem(VisualTreeHelper.GetChild(d, i))));
        }

        public ObservableCollection<VisualTreeItem> Children { get; private set; }

        public string DisplayString
        {
            get
            {
                return _d.ToString();
            }
        }
    }
}

image

WordPress.com で無料サイトやブログを作成.