WPF和动态显示用户控件在一个用户控件

本文关键字:用户 控件 一个 动态显示 WPF | 更新日期: 2023-09-27 18:18:01

我正在使用WPF和MVVM Light框架。在我的项目中,我有一个GameViewModel和一个相关的视图,作为我的游戏的主屏幕(这不是我的主要ViewModel)。在GameView中,我想动态地显示其他usercontrol,由按钮点击或类似的东西触发,在网格中的特定位置。我不太确定该怎么做。我想过使用第二个ViewModelLocator或类似的东西(我根本不确定如何去做),但在我深入研究之前,我想我应该在这里问一下,看看是否有更实用的方法来做到这一点。

假设单击一个按钮,UserControl1显示在网格上的3,3位置,然后单击另一个按钮,UserControl2显示在同一位置。这就是我想要实现的。虽然这不是必须的,但我希望尽可能多地使用XAML和尽可能少地使用后台代码,但是任何以对mvvm友好的方式完成工作的方法对我来说都非常好。如果您能给我任何建议,我将不胜感激。我猜解决办法可能比我想象的要简单得多……通常是这样。

WPF和动态显示用户控件在一个用户控件

我在最近的一个项目中使用的一个想法是将元素的Visibility属性绑定到ViewModel中的Visibility属性。然后你可以在ViewModel中处理所有的显示逻辑。

Visibility="{Binding ElementVisibility}"

然后在ViewModel中你会有一个像

这样的属性
public const string ElementVisibilityPropertyname = "ElementVisibility";
private Visibility _elementVisibility = Visibility.Collapsed;
public Visibility ElementVisibility
{
    get
    {
        return _elementVisibility;
    }
    set
    {
        if (_elementVisibility== value)
        {
            return;
        }
        RaisePropertyChanging(ElementVisibilityPropertyname );
        _elementVisibility= value;
        RaisePropertyChanged(ElementVisibilityPropertyname );
    }
}

在你的按钮中,你可以像这样绑定Command属性:

Command="{Binding ShowElement}"

然后在ViewModel中你会提供RelayCommand

private RelayCommand _showElement;
public RelayCommand ShowElement
{
    get
    {
        return _showElement?? (_showElement= new RelayCommand(() =>
                             {
                                 this.ElementVisibility = Visibility.Visible;
                             ));
    }
}

希望这能让你在你正在寻找的方向!

我写过一篇类似的博文;

http://pjgcreations.blogspot.co.uk/2013/03/wpf-programmatically-adding-buttons.html

下面的代码使用了一个Canvas,一个ItemPresenter和一个DataTemplate来显示在运行时从ViewModel中填充的按钮。

XAML:

<Window x:Class="MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
    <Canvas x:Name="MyCanvas">
        <ItemsControl ItemsSource="{Binding MyButtons}" Height="237" Width="507">
            <ItemsControl.ItemsPanel >
                <ItemsPanelTemplate>
                    <Canvas IsItemsHost="true"></Canvas>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Button Margin="{Binding ControlMargin}" Content="{Binding Content}" Command="{Binding DataContext.ButtonCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" CommandParameter="{Binding ProductId}"></Button>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </Canvas>
</Window>

一个流体按钮类;

Public Class FluidButton
    Public Property Content As String
    Public Property LeftPos As Double
    Public Property TopPos As Double
    Public Property ProductId As Double
    'Returns the Control Margin, using the Class Properties
    Public ReadOnly Property ControlMargin As Thickness
        Get
            Return New Thickness With {.Left = LeftPos, .Top = TopPos}
        End Get
    End Property
End Class

'Our Collection of Buttons or Products
Public Property MyButtons As ObservableCollection(Of FluidButton)
'Used to expose the Button Pressed Execute Commands to the UI for Binding
Public Property ButtonCommand As DelegateCommand

MyButtons = New ObservableCollection(Of FluidButton)
MyButtons.Add(New FluidButton With {.Content = "Test1", .LeftPos = 0, .TopPos = 20, .ProductId = 1})
MyButtons.Add(New FluidButton With {.Content = "Test2", .LeftPos = 40, .TopPos = 30, .ProductId = 2})
MyButtons.Add(New FluidButton With {.Content = "Test3", .LeftPos = 80, .TopPos = 40, .ProductId = 3})
MyButtons.Add(New FluidButton With {.Content = "Test4", .LeftPos = 120, .TopPos = 50, .ProductId = 4})
MyButtons.Add(New FluidButton With {.Content = "Test5", .LeftPos = 160, .TopPos = 60, .ProductId = 5})

我相信你可以很容易地修改它来满足你的需要