泥庭

2013年5月30日

Gridへのアイテムのバインド(StoreApps編)

Filed under: .NET, ストアアプリ, Windows8 — タグ: — yone64 @ 10:03 PM

前回の続き。

StoreAppsの場合、StyleのSetterでBindingを差し込むことができないため、CustomControlを作成する必要があります。たとえば、以下のような感じです。

public sealed class BindableGrid : ItemsControl
{
    protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
    {
        base.PrepareContainerForItemOverride(element, item);

        var container = element as FrameworkElement;
        Binding binding1 = new Binding();
        binding1.Mode = BindingMode.OneTime;
        binding1.Source = item;
        binding1.Path = new PropertyPath("ColumnIndex");

        Binding binding2 = new Binding();
        binding2.Mode = BindingMode.OneTime;
        binding2.Source = item;
        binding2.Path = new PropertyPath("RowIndex");

        container.SetBinding(Grid.ColumnProperty, binding1);
        container.SetBinding(Grid.RowProperty, binding2);
    }
}

これで、XAML側をItemsControlから、カスタムコントロールに切り替えれば、終了。XAMLだけで完結しないあたりが、とても残念。

2013年5月29日

Gridへのアイテムのバインド(WPF編)

Filed under: .NET, WPF — タグ: — yone64 @ 11:55 PM

めっちゃ久しぶりにWPFのお話、

Gridは、コントロールをマス目で並べるときにとっても便利なコントロールです。たとえば、以下のようなレイアウトは、Gridが得意とするものの一つです。

image

この場合の、XAMLは以下の通りです。簡潔でよいのですが、子要素がXAML上に固定されているのは扱いづらいので、駒情報のコレクションをBindingすることで、XAMLから分離したいところです。

<Window x:Class="WPFBindSample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="525" Width="525">
    <Grid ShowGridLines="True" Background="LightGreen">
        <Grid.ColumnDefinitions>
            <ColumnDefinition></ColumnDefinition>
            <ColumnDefinition></ColumnDefinition>
            <ColumnDefinition></ColumnDefinition>
            <ColumnDefinition></ColumnDefinition>
            <ColumnDefinition></ColumnDefinition>
            <ColumnDefinition></ColumnDefinition>
            <ColumnDefinition></ColumnDefinition>
            <ColumnDefinition></ColumnDefinition>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
        </Grid.RowDefinitions>
        <Ellipse Grid.Column="4" Grid.Row="4" Margin="5" Fill="White"/>
        <Ellipse Grid.Column="3" Grid.Row="3" Margin="5" Fill="White"/>
        <Ellipse Grid.Column="3" Grid.Row="4" Margin="5" Fill="Black"/>
        <Ellipse Grid.Column="4" Grid.Row="3" Margin="5" Fill="Black"/>
    </Grid>
</Window>

しかし、GridはItemsControlのサブクラスではないため、ItemsSouceプロパティーは存在せず、したがってCollectionとのBindingもできません。残念! こういう場合はどうするかというと、ItemsControlを利用しCollectionとのBindingをしつつ、ItemPanelでGridを指定することになります。XAMLは以下の通り。

<Window x:Class="WPFBindSample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WPFBindSample"
        Title="MainWindow" Height="525" Width="525">

    <Window.Resources>
        <local:ColorToSolidColorBrushValueConverter  x:Key="ColorBrushConverter"/>
    </Window.Resources>
    <ItemsControl ItemsSource="{Binding}">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <Grid Background="LightGreen" ShowGridLines="True">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition></ColumnDefinition>
                        <ColumnDefinition></ColumnDefinition>
                        <ColumnDefinition></ColumnDefinition>
                        <ColumnDefinition></ColumnDefinition>
                        <ColumnDefinition></ColumnDefinition>
                        <ColumnDefinition></ColumnDefinition>
                        <ColumnDefinition></ColumnDefinition>
                        <ColumnDefinition></ColumnDefinition>
                    </Grid.ColumnDefinitions>
                    <Grid.RowDefinitions>
                        <RowDefinition></RowDefinition>
                        <RowDefinition></RowDefinition>
                        <RowDefinition></RowDefinition>
                        <RowDefinition></RowDefinition>
                        <RowDefinition></RowDefinition>
                        <RowDefinition></RowDefinition>
                        <RowDefinition></RowDefinition>
                        <RowDefinition></RowDefinition>
                    </Grid.RowDefinitions>
                </Grid>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemContainerStyle>
            <Style>
                <Setter Property="Grid.Column" Value="{Binding Path=ColumnIndex}"/>
                <Setter Property="Grid.Row" Value="{Binding Path=RowIndex}"/>
            </Style>
        </ItemsControl.ItemContainerStyle>
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <Ellipse  Margin="5"
                    Fill="{Binding Path=Color,
                    Converter={StaticResource ResourceKey=ColorBrushConverter}}"/>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
</Window>

ポイントは、ItemContainerStyleでStyleを利用しGrid.ColunとGridRowに対してBindingを設定しているところ。これにより、Grid上の位置をBidingで設定することが可能になります。このXAMLに対して、コードビハインドで、以下のようなDataを設定してあげると、当初と同じ画面が表示されます。

this.DataContext = new[]
{
    new {Color = Colors.White, ColumnIndex = 3, RowIndex = 3},
    new {Color = Colors.White, ColumnIndex = 4, RowIndex = 4},
    new {Color = Colors.Black, ColumnIndex = 3, RowIndex = 4},
    new {Color = Colors.Black, ColumnIndex = 4, RowIndex = 3},
};

WPFだとこんな感じでできますが、Storeアプリだとこの方法はうまくいきません。詳しくは次回。

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