I have a list of rectangles that I want to display on a canvas. I used Krzysztof Skowronek's answer to this question, but he doesn't use ReactiveUI Binding; I am. But I can't get any of my rectangles to show up on my canvas. Everything compiles with no errors and there are no exceptions being thrown. There's not much to this code because I created a new project just to test this out before adding it to my actual project. Here's what I got.
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);
}
}
}
I checked that the command is working using breakpoints.
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);
});
}
}
}
If there's anything else you need to know I'll add it, but I can't think of anything.
I am using WPF and have the following NuGet Packages installed. ReactiveUI, ReactiveUI.WPF, ReactiveUI.Events.WPF; all v11.4.17.