Agregue n rectángulos al lienzo con MVVM en WPF

Resuelto Philipp Eger asked hace 10 años • 2 respuestas

Quiero agregar un conjunto de rectángulos a la ventana principal de mi aplicación mvvm. En mi viewModel tengo una colección de objetos que convierto a clases System.Windows.Shapes.Rectangle con un convertidor (código a continuación):

Ver modelo:

RecognizedValueViewModel 
{
    public ObservableCollection<BarcodeElement> BarcodeElements
    {
        get { return _BarcodeElements; }
        set { _BarcodeElements = value; }
    }

    public RecognizedValueViewModel()
    {
        BarcodeElements = InitializeBarcodeElements();
    }
}

Convertidor:

public BarcodeElementToRectangleConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        Rectangle barcodeRectangle = GetRectangleFromBarcodeElement(value as BarcodeElement);

        return barcodeRectangle;
    }
}

Los rectángulos deberían mostrarse en un lienzo en mi ventana principal:

<Canvas x:Name="Canvas_Image_Main">
    <!-- Show rectangles here -->
</Canvas>

Agregaría rectángulos al lienzo en el código, pero no sé cuántos rectángulos hay en tiempo de ejecución. ¿Hay alguna manera de lograr esto? Gracias.

Philipp Eger avatar Mar 11 '14 18:03 Philipp Eger
Aceptado

En un enfoque MVVM adecuado, tendrías un modelo de vista con una representación abstracta de una lista de rectángulos, por ejemplo, así:

public class RectItem
{
    public double X { get; set; }
    public double Y { get; set; }
    public double Width { get; set; }
    public double Height { get; set; }
}

public class ViewModel
{
    public ObservableCollection<RectItem> RectItems { get; set; }
}

Entonces tendría una vista que utiliza ItemsControl para visualizar una colección de dichos Rectelementos. ItemsControl tendría un Canvas como ItemsPanelapropiado ItemContainerStyley ItemTemplatecada uno de los cuales se vincularía a las propiedades del modelo de vista apropiadas. Podría verse así:

<ItemsControl ItemsSource="{Binding RectItems}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <Canvas/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemContainerStyle>
        <Style TargetType="ContentPresenter">
            <Setter Property="Canvas.Left" Value="{Binding X}"/>
            <Setter Property="Canvas.Top" Value="{Binding Y}"/>
        </Style>
    </ItemsControl.ItemContainerStyle>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Rectangle Width="{Binding Width}" Height="{Binding Height}" Fill="Black"/>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

Una alternativa sin enlaces en Definidores de estilo (que no funcionan en UWP) podría verse así:

<ItemsControl ItemsSource="{Binding RectItems}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <Canvas/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Rectangle Width="{Binding Width}" Height="{Binding Height}" Fill="Black">
                <Rectangle.RenderTransform>
                    <TranslateTransform X="{Binding X}" Y="{Binding Y}"/>
                </Rectangle.RenderTransform>
            </Rectangle>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>
Clemens avatar Mar 11 '2014 12:03 Clemens

Puede vincular la colección de rectángulos a un ItemControl y establecer su alto, ancho y margen:

<ItemsControl  ItemsSource="{Binding Path=RectangleCollection,Mode=TwoWay}">
    <ItemsControl.ItemTemplate>
        <DataTemplate >
            <Canvas>
                <Rectangle Stroke="Black" Heigth={some converter} Width={some converter} Margin={Some Converter}>
            </Canvas>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemControl>

Sólo una idea para empezar...

Abhinav Sharma avatar Mar 11 '2014 11:03 Abhinav Sharma