Как отобразить коллекцию ObservableCollection прямоугольников на холсте с помощью ReactiveUI? - PullRequest
0 голосов
/ 20 июня 2020

У меня есть список прямоугольников, которые я хочу отобразить на холсте. Я использовал ответ Кшиштофа Сковронека на этот вопрос , но он не использует ReactiveUI Binding; Я. Но я не могу заставить ни один из моих прямоугольников отображаться на моем холсте. Все компилируется без ошибок и исключений не возникает. В этом коде не так много, потому что я создал новый проект только для того, чтобы протестировать его, прежде чем добавлять его в свой настоящий проект. Вот что у меня получилось.

MainWindowViewModel.cs

namespace CanvasTest
{
    public class MainWindowViewModel : ReactiveObject
    {
        //test canvas implementation
        private ObservableCollection<IShape> _shapes;
        public ObservableCollection<IShape> Shapes
        {
            get => _shapes;
            set => this.RaiseAndSetIfChanged(ref _shapes, value);
        }

        public ReactiveCommand<Unit, Unit> AddRectangle { get; }

        public MainWindowViewModel()
        {
            // Test Canvas Implementation
            Shapes = new ObservableCollection<IShape>();

            AddRectangle = ReactiveCommand.Create<Unit>(x => { 
                Shapes.Add(new Rectangle { Top = 25, Left = 10, Height = 50, Width = 50 });
            });
        }
    }

    public interface IShape
    {
        int Top { get; set; }
        int Left { get; set; }
    }

    public abstract class Shape : ReactiveObject, IShape
    {
        private int _top;
        public int Top
        {
            get => _top;
            set => this.RaiseAndSetIfChanged(ref _top, value);
        }

        private int _left;
        public int Left
        {
            get => _left;
            set => this.RaiseAndSetIfChanged(ref _left, value);
        }
    }

    public class Rectangle : Shape
    {
        private int _width;
        public int Width
        {
            get => _width;
            set => this.RaiseAndSetIfChanged(ref _width, value);
        }

        private int _height;
        public int Height
        {
            get => _height;
            set => this.RaiseAndSetIfChanged(ref _height, value);
        }
    }
}

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

MainWindow. xaml

<rxui:ReactiveWindow x:Class="CanvasTest.MainWindow"
        x:TypeArguments="ct:MainWindowViewModel"
        xmlns:rxui ="http://reactiveui.net"
        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:ct="clr-namespace:CanvasTest"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>

        <ItemsControl x:Name="audioDisplayItemsControl" 
                      BorderBrush="Black"
                      BorderThickness="2"
                      Height="100">
            <ItemsControl.Resources>
                <DataTemplate DataType="{x:Type ct:Rectangle}">
                    <Rectangle Canvas.Top="{Binding Top, Mode=OneWay}" 
                               Canvas.Left="{Binding Left, Mode=OneWay}"
                               Width="{Binding Width}"
                               Height="{Binding Height}"
                               Fill="Green"/>
                </DataTemplate>
            </ItemsControl.Resources>
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <Canvas/>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ItemsControl.ItemContainerStyle>
                <Style TargetType="ContentPresenter">
                    <Setter Property="Canvas.Top" Value="{Binding Top, Mode=OneWay}"/>
                    <Setter Property="Canvas.Left" Value="{Binding Left, Mode=OneWay}"/>
                </Style>
            </ItemsControl.ItemContainerStyle>
        </ItemsControl>
        
        <Button x:Name="addButton" 
                Grid.Row="1" 
                Content="Add" 
                Width="50"
                Margin="0,0,0,10"/>
    </Grid>
</rxui:ReactiveWindow>

MainWindow.xaml.cs

namespace CanvasTest
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : ReactiveWindow<MainWindowViewModel>
    {
        public MainWindow()
        {
            InitializeComponent();
            ViewModel = new MainWindowViewModel();

            this.WhenActivated(d =>
            {
                this.OneWayBind(ViewModel,
                    vm => vm.Shapes,
                    v => v.audioDisplayItemsControl.ItemsSource)
                 .DisposeWith(d);

                this.BindCommand(ViewModel,
                    vm => vm.AddRectangle,
                    v => v.addButton)
                .DisposeWith(d);
            });
        }
    }
}

Если вам еще что-нибудь нужно знать, я добавлю это, но могу Я ни о чем не думаю.

Я использую WPF, и у меня установлены следующие пакеты NuGet. ReactiveUI, ReactiveUI.WPF, ReactiveUI.Events.WPF; все v11.4.17.

1 Ответ

0 голосов
/ 21 июня 2020

В соответствии с моим комментарием выше я добавил контекст данных в заголовок MainWindow.xaml, чтобы я мог привязаться к коллекции в моей ViewModel:

DataContext="{Binding RelativeSource={RelativeSource Self}, Path=ViewModel}"

и сделал привязку XAML к моей Shapes ObservableCollection

<ItemsControl ItemsSource="{Binding Shapes}" ... >

Поговорив с Ани Беттс по каналу reactiveui Slack, я обнаружил, что это лучший способ сделать это. Вы можете заставить его работать, указав шаблон данных для привязки rxui; это создает много накладных расходов, и, поскольку холст не перерабатывается, с большим количеством элементов холста, это может быть дорогостоящим с точки зрения памяти.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...