none
【MVVM】WPFのCanvasコントロールのChildrenをバインドしたい RRS feed

  • 質問

  • ViewAの中にCanvasコントロールがありCanvasの子に持たすオブジェクトを動的に変えたいです。

    (Canvasをクリックすると、その座標にRectangleを配置します。)

    ViewBに配置しているボタン押下でRectangleの操作(削除)をするため、

    ViewAのコードビハインドでCanvas.Children.Add(Rectangle)でオブジェクトを追加するのではなく

    ViewModelで操作したいです。

    Childrenプロパティをバインドするにはどのようにすればよいでしょうか?
    2018年11月12日 15:08

回答

  • CanvasのChildrenにバインドではなく、ItemsControlやListBoxのパネルにCanvasを指定します

    <Window x:Class="WpfApp1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:WpfApp1"
            mc:Ignorable="d" Title="MainWindow" Height="450" Width="800">
        <Grid>
            <ListBox ItemsSource="{Binding Path=Children}">
                <ListBox.ItemsPanel>
                    <ItemsPanelTemplate>
                        <Canvas />
                    </ItemsPanelTemplate>
                </ListBox.ItemsPanel>
    
                <ListBox.ItemContainerStyle>
                    <Style TargetType="{x:Type ListBoxItem}">
                        <Setter Property="Canvas.Left" Value="{Binding Path=X}"/>
                        <Setter Property="Canvas.Top" Value="{Binding Path=Y}"/>
                    </Style>
                </ListBox.ItemContainerStyle>
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <Rectangle Width="{Binding Path=Width}" Height="{Binding Path=Height}" Fill="{Binding Path=Color}"/>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>
        </Grid>
    </Window>
    namespace WpfApp1
    {
        using System.Windows;
        using System.Windows.Media;
    
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
    
                var model = new Model();
                model.Children.Add(new Item() { X = 50, Y = 100, Width = 50, Height = 50, Color = new SolidColorBrush(Colors.Red) });
                model.Children.Add(new Item() { X = 200, Y = 150, Width = 10, Height = 10, Color = new SolidColorBrush(Colors.Green) });
                model.Children.Add(new Item() { X = 100, Y = 300, Width = 50, Height = 20, Color = new SolidColorBrush(Colors.Blue) });
    
                this.DataContext = model;
            }
        }
    
        class Model
        {
            public Model()
            {
                Children = new System.Collections.ObjectModel.ObservableCollection<Item>();
            }
            public System.Collections.ObjectModel.ObservableCollection<Item> Children { get; private set; }
        }
    
        class Item
        {
            public double X { get; set; }
            public double Y { get; set; }
            public double Width { get; set; }
            public double Height { get; set; }
            public SolidColorBrush Color { get; set; }
        }
    }

    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    • 回答としてマーク arutan 2018年11月13日 14:32
    2018年11月12日 22:55

すべての返信

  • CanvasのChildrenにバインドではなく、ItemsControlやListBoxのパネルにCanvasを指定します

    <Window x:Class="WpfApp1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:WpfApp1"
            mc:Ignorable="d" Title="MainWindow" Height="450" Width="800">
        <Grid>
            <ListBox ItemsSource="{Binding Path=Children}">
                <ListBox.ItemsPanel>
                    <ItemsPanelTemplate>
                        <Canvas />
                    </ItemsPanelTemplate>
                </ListBox.ItemsPanel>
    
                <ListBox.ItemContainerStyle>
                    <Style TargetType="{x:Type ListBoxItem}">
                        <Setter Property="Canvas.Left" Value="{Binding Path=X}"/>
                        <Setter Property="Canvas.Top" Value="{Binding Path=Y}"/>
                    </Style>
                </ListBox.ItemContainerStyle>
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <Rectangle Width="{Binding Path=Width}" Height="{Binding Path=Height}" Fill="{Binding Path=Color}"/>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>
        </Grid>
    </Window>
    namespace WpfApp1
    {
        using System.Windows;
        using System.Windows.Media;
    
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
    
                var model = new Model();
                model.Children.Add(new Item() { X = 50, Y = 100, Width = 50, Height = 50, Color = new SolidColorBrush(Colors.Red) });
                model.Children.Add(new Item() { X = 200, Y = 150, Width = 10, Height = 10, Color = new SolidColorBrush(Colors.Green) });
                model.Children.Add(new Item() { X = 100, Y = 300, Width = 50, Height = 20, Color = new SolidColorBrush(Colors.Blue) });
    
                this.DataContext = model;
            }
        }
    
        class Model
        {
            public Model()
            {
                Children = new System.Collections.ObjectModel.ObservableCollection<Item>();
            }
            public System.Collections.ObjectModel.ObservableCollection<Item> Children { get; private set; }
        }
    
        class Item
        {
            public double X { get; set; }
            public double Y { get; set; }
            public double Width { get; set; }
            public double Height { get; set; }
            public SolidColorBrush Color { get; set; }
        }
    }

    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    • 回答としてマーク arutan 2018年11月13日 14:32
    2018年11月12日 22:55
  • ご回答ありがとうございました。

    はじめてみるものがたくさんですが、記載いただいたサンプルコードを見つつ勉強させていただきます。

    2018年11月13日 14:32