WPF Canvas, как динамически добавлять дочерние элементы с помощью кода MVVM

#wpf #mvvm #canvas #dynamic #children

#wpf #mvvm #canvas #динамический #дочерние элементы

Вопрос:

Требование:

Нарисовать одно растровое изображение и прямоугольник (ы) на основе набора точек. Прямоугольник должен точно соответствовать расположению пикселей над изображением. Также необходимо добавить некоторый текст внутри прямоугольника.

Изображение всегда будет только одним, и прямоугольники будут добавляться динамически.

Текущее решение:

Создайте холст с управлением изображениями. Добавьте динамический код в код, лежащий в основе файла ViewImageResult.xaml.cs.

     private void DrawResult(int left, int right, int width, int height)
    {
        Border bord = new Border();
        bord.BorderThickness = new Thickness(1);
        bord.BorderBrush = Brushes.Red;
        bord.Width = width;
        bord.Height = height;
        _mainCanvas.Children.Add(bord);
        Canvas.SetLeft(bord, left);
        Canvas.SetTop(bord, right);
    }
  

Проблема:

Поскольку я следую шаблону MVVM, коллекция точек для прямоугольника находится в моем файле ViewModel ViewImageResultModel.cs. Я не могу динамически добавлять дочерний прямоугольник из файла ViewModel.

Ответ №1:

ItemsControl твой друг:

 <Grid>
    <Image Source="..."/>
    <ItemsControl ItemsSource="{Binding Points}">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <Canvas/>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemContainerStyle>
            <Style>
                <Setter Property="Canvas.Left" Value="{Binding X}"/>
                <Setter Property="Canvas.Top" Value="{Binding Y}"/>
            </Style>
        </ItemsControl.ItemContainerStyle>
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <Border BorderBrush="Red" BorderThickness="1" Width="{Binding Width}" Height="{Binding Height}"/>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
</Grid>
  

Вышесказанное предполагает, что ваша виртуальная машина предоставляет набор точек с помощью Points свойства, и что каждая виртуальная точка имеет X , Y Width и Height свойства.

Комментарии:

1. Большое спасибо, Кент. Это великолепно работает с небольшими изменениями <Canvas IsItemsHost=»True» />

2. Это … это просто прекрасно.

Ответ №2:

Добавлено IsItemsHost="True" в Canvas решение Кента:

 <Grid>
    <Image Source="..."/>
    <ItemsControl ItemsSource="{Binding Points}">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <Canvas  IsItemsHost="True"/>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemContainerStyle>
            <Style>
                <Setter Property="Canvas.Left" Value="{Binding X}"/>
                <Setter Property="Canvas.Top" Value="{Binding Y}"/>
            </Style>
        </ItemsControl.ItemContainerStyle>
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <Border BorderBrush="Red" BorderThickness="1" Width="{Binding Width}" Height="{Binding Height}"/>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
</Grid>
  

Комментарии:

1. Приятно думать о наборе текста, а не о разговоре, потому что, когда вы осознаете свою ошибку, вам не нужно нажимать «Добавить комментарий»…