WPF& MVVM Light - 在UserControl中动态显示UserControl

时间:2013-06-11 23:02:10

标签: c# wpf mvvm

我正在使用WPF和MVVM Light框架。在我的项目中,我有一个GameViewModel和一个相关的视图,它作为我游戏的主屏幕(这不是我的主要ViewModel)。在GameView中,我想在网格中的某个位置动态显示由按钮点击或某种性质触发的其他UserControl。我不完全确定如何解决这个问题。我想过使用一个辅助的ViewModelLocator或类似的东西(我根本不知道该怎么做),但在我深入研究之前,我想我会问这里,看看是否还有更实用的方法做这个。

单击按钮,UserControl1在网格上显示为3,3,然后单击另一个按钮,UserControl2显示在同一位置。这基本上就是我想要完成的。虽然不是必须的,但我希望尽可能多地使用XAML和尽可能少的代码隐藏,但是以MVVM友好的方式完成工作的任何事情对我来说都是完美的。您将给予的任何建议将不胜感激。我猜这个解决方案可能比我实现它要容易得多......它通常是。

2 个答案:

答案 0 :(得分:2)

我在最近的项目中使用的一个想法是将元素的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 );
    }
}

在你的Button中你会像这样绑定Command属性:

Command="{Binding ShowElement}"

然后在ViewModel中提供一个RelayCommand

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

希望这能让你朝着你想要的方向前进!

答案 1 :(得分:1)

我在这里发了一篇关于类似于similair的博客文章;

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

ViewModel中的属性;

'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})

我确信您可以轻松修改它以满足您的需求