c# - 具有不同数量对象的 WPF MVVM View 。如何?

标签 c# wpf mvvm

嗨! 我想设计将在不同位置包含多个对象的 View 。例如 - 如果 viewmodel 可以具有像对象列表(矩形)这样的字段,并且当我将成员更改/添加到列表时,新矩形会出现在指定位置的 View 中,那就太好了。 我如何创建这样的 View / View 模型?

最佳答案

你可以有一个 ICollectionViewObservableCollection<T> ViewModel 中的属性并绑定(bind) ItemsSource ItemsControl 的属性到这个属性。然后这将显示您的收藏( View )中的所有项目。但是,它通常会将它们显示在 StackPanel 中。因为这是 ItemsControl 的默认项目容器.据我了解您的问题,您希望将项目放置在屏幕上的任何位置。这可以通过使用 Canvas 来完成。作为 ItemsControlItemsPanel , 然后绑定(bind) Canvas.LeftCanvas.Top属性到 ViewModel 中的属性。当然,每个项目都需要 LeftTop然后属性(也可能是 WidthHeight 属性)。

public class ItemViewModel
{
    public double Left { get; set; }
    public double Top { get; set; }
    public double Width { get; set; }
    public double Height { get; set; }

    // whatever you need...
}

public class CollectionViewModel
{
    public ObservableCollection<ItemViewModel> Collection { get; }

    // some code which fills the Collection with items
}

还有你的 XAML:

<ItemsControl ItemsSource="{Binding Collection}">

    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <Canvas/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>

    <ItemsControl.ItemTemplate>
        <DataTemplate DataType="{x:Type local:ItemViewModel}">
            <Rectangle Width="{Binding Width}" Height="{Binding Height}"
                       Canvas.Left="{Binding Left}" Canvas.Top="{Binding Top}"/>
        </DataTemplate>
    </ItemsControl.ItemTemplate>

</ItemsControl>

在最后一步,您可能需要 LeftTop属性与 Canvas 的大小相关, 如果 Canvas 的大小,则项目保留在相对位置变化。这是一些更多的工作:

<DataTemplate DataType="{x:Type local:ItemViewModel}">
    <Rectangle Width="{Binding Width}" Height="{Binding Height}">

        <!-- Make the left position of the item depend on the ActualWidth of the Canvas,
             the relative Left position (between 0 and 1) from the ItemViewModel, and the ActualWidth
             of the item itself. This is needed because the Canvas.Left property defines the
             position of the left side, not the center. Therefore, we calculate the position of
             the center this way:
                  (Canvas.ActualWidth * ItemViewModel.Left) - (Item.ActualWidth / 2)
        -->
        <Canvas.Left>
            <MultiBinding>
                <MultiBinding.Converter>
                    <converters:ExpressionConverter Expression="{}({0} * {1}) - ({2} / 2)"/>
                </MultiBinding.Converter>
                <Binding Path="ActualWidth" RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type Canvas}}"/>
                <Binding Path="Left"/>
                <Binding Path="ActualWidth" RelativeSource="{RelativeSource Self}"/>
            </MultiBinding>
        </Canvas.Left>

        <!-- the top position of the items is determined the same way as the left position
             which is described above -->
        <Canvas.Top>
            <MultiBinding>
                <MultiBinding.Converter>
                    <converters:ExpressionConverter Expression="{}({0} * {1}) - ({2} / 2)"/>
                </MultiBinding.Converter>
                <Binding Path="ActualHeight" RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type Canvas}}"/>
                <Binding Path="Top"/>
                <Binding Path="ActualHeight" RelativeSource="{RelativeSource Self}"/>
            </MultiBinding>
        </Canvas.Top>

    </Rectangle>
</DataTemplate>

代码的描述已经在 XAML 注释中。但是,我应该注意我使用了 ExpressionConverter来自 Kent Boogart's Converter collection .我从我的一个应用程序中复制并粘贴了上面的代码,因此由于根据您的情况快速调整了属性,因此其中可能存在一些不一致之处。但是,我认为原则应该很清楚。祝你好运!

关于c# - 具有不同数量对象的 WPF MVVM View 。如何?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2957159/

相关文章:

c# - 具有泛型类声明的命名空间约束

c# - 调度程序不执行作业,似乎甚至没有注册它

c# - 剪贴板.设置比较

c# - 从多个线程写入 TraceListener

android - ViewModelFactory无法正确实例化ViewModel

c# - 使用 MVVM,我们应该在哪里调用来启用或禁用 UI?

json - Swift MVVM 如何实现数组来建模

c# - 传递带有哈希值的 URL 以进行重定向

c# - Entity Framework - 重用复杂类型

c# - 当我创建 WPF 窗口时,Windows 窗体窗口改变了它的大小