【问题标题】:Create XAML canvas programmatically using MVVM使用 MVVM 以编程方式创建 XAML 画布
【发布时间】:2026-01-21 01:10:01
【问题描述】:

我正在使用Elysium 框架来使用ApplicationBar 控件,并且我想让它的CommandButton 动态地用于我的视图。因此,我将其ItemsSource 属性绑定到ObservableCollection<CommandButton>,每个视图都会创建自己的操作。

在使用Elysium之前,我有这个按钮:

<Button>
    <Canvas Width="60" Height="60" Clip="F1 M 0,0L 76,0L 76,76L 0,76L 0,0">
        <Path Width="27.854" Height="31.076" Canvas.Top="14" Fill="White" 
              Data="F1 M 51.5487,37.9814L 56.814,41.0534L 50.3383,48.7636L 50.3383,48.8841L 60.0205,46.9565L 60.0205,53.0403L 50.2777,51.414L 50.2777,51.5344L 56.814,59.0037L 51.4882,62.0757L 47.978,52.7994L 47.8569,52.7994L 44.4072,62.0757L 39.2025,59.0037L 45.6782,51.4742L 45.6177,51.3537L 36.1159,53.0403L 36.1159,46.9565L 45.5571,48.8841L 45.5571,48.7636L 39.2025,41.1137L 44.5888,37.9814L 47.9174,47.3179L 48.0385,47.3179L 51.5487,37.9814 Z M 20,17L 43.25,17L 56,29.75L 56,39L 52,36.75L 52,34L 39,34L 39,21L 24,21L 24,55L 41,55L 37.5,59L 20,59L 20,17 Z M 43,22.25L 43,30L 50.75,30L 43,22.25 Z " Canvas.Left="17.24" Stretch="Fill"/>
    </Canvas>
</Button>

这就是我在视图上创建操作的方式。

CommandButtonList.Add(new CommandButton
{
    Header = "new version"
});

我想知道是否可以通过编程方式创建&lt;Canvas&gt;?如果是,那又如何?

请记住我使用的是 MVVM

编辑:

每个动作都会有不同的&lt;Canvas&gt;&lt;Path&gt;

【问题讨论】:

    标签: c# wpf xaml canvas mvvm


    【解决方案1】:

    如果您在要绑定的 ViewModel 中存储 CommandButton 的集合(即 UiElement),那么您已经违反了 MVVM 的主要“规则”之一:ViewModel 中没有视图。如果您想真正走 MVVM 路线,请将您的集合更改为某种数据类型,然后使用 DataTemplates 在 XAML 中处理 UI 控件(CommandButtonCanvas 等)的设置。如果您想坚持当前的方向,那么您不妨直接创建并分配CanvasCommandButton 创建。

    您的集合数据项的外观完全取决于需要在每个按钮上进行不同设置的内容。如果您考虑手动创建一组按钮,则每个不同的属性都应该绑定到该按钮的数据项上的一个字段。数据可以像字符串集合一样简单。这可以用于每个按钮上的不同光栅图像(许多不同的位置选项):

    CommandButtonList = new ObservableCollection<string>
    {
        "http://foo.com/image1.jpg",
        @"c:\images\image2.jpg",
        "/ProjectImages/image3.jpg"
    };
    

    然后你绑定到它的ItemsControl 会将它的ItemTemplate 设置为这样的:

    <DataTemplate>
        <Button>
            <Image Source="{Binding}"/>
        </Button>
    </DataTemplate>
    

    现在绑定使用集合中的字符串。这显然是一个简单的示例,您可以做很多额外的变化:具有大量属性的更复杂的数据对象,具有大量绑定的更复杂的模板,同一 ItemsControl 上的多个数据模板,模板 DataTypeTemplateSelector

    【讨论】:

    • 这确实是一个很好的观点。您能否提供一些代码来向我展示如何创建此数据类型集合以与 DataTemplate 链接?如果我这样做,我怎么能确定我的所有按钮都不会有相同的图像?
    • 如果我选择坚持我目前的方向,我该如何创建和分配Canvas
    • 添加了示例。另一种方式,Canvas 只是一个对象,你想将它分配给一个属性,可能是 Content 或 Header,所以 new CommandButton { Header = new Canvas() };
    • 约翰,谢谢你的回答。你的例子和你的句子“你打破了 MVVM 的主要规则”真的帮助了我,这让我付出了一些努力并为这种情况编写了适当的代码。