如何动态地将控件添加到另一个类的WrapPanel中?

时间:2013-05-03 20:05:49

标签: c# .net wpf

我正在从VB迁移到C#,并认为WPF对我来说是最好的选择,因为我一直在开发的程序是基于GUI的高度依赖的应用程序。但是,在尝试获取VB中用于C#代码的简单任务时,C#给我带来了很多麻烦,困惑和沮丧。在VB中,我可以很容易地使用它。但是在C#中,在花了无数个小时(现在几天)搜索和玩代码之后,我仍然不知道如何让它工作。

我的情景:

  • 我有2个xaml页面。
  • 第一个xaml页面有一个wrappanel。
  • 第二个xaml页面有一个按钮,它将创建一个新按钮并将其添加到第1页的xaml中的wrappanel。

使用page1.xaml.cs中的以下代码时,我可以轻松地向wrappanel添加一个新按钮:

Button New_Button = new Button();
My_WrapPanel.Children.Add(New_Button);

我也试过调用第2页第1页的方法来创建按钮,但新的按钮没有显示在wrappanel中??

我真的很感激一些帮助,可能还有一个简单的代码示例来帮助我。

1 个答案:

答案 0 :(得分:6)

好的,我使用UserControl而不是Page来将它们保存在一个窗口中。由于你没有发布任何XAML,我不知道你真正的需求是什么,但这是我的看法:

MultiPageSample.xaml(“主窗口”):

<Window x:Class="MiscSamples.MultiPageMVVM.MultiPageSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:MiscSamples.MultiPageMVVM"
        Title="MultiPageSample" Height="300" Width="300">
    <UniformGrid Rows="1" Columns="2">
        <local:Page1 DataContext="{Binding Page1}"/>
        <local:Page2 DataContext="{Binding Page2}"/>
    </UniformGrid>
</Window>

代码背后:

public partial class MultiPageSample : Window
{
    public MultiPageSample()
    {
        InitializeComponent();

        DataContext = new MultiPageViewModel();
    }
}

视图模型:

public class MultiPageViewModel
{
    public Page1ViewModel Page1 { get; set; }

    public Page2ViewModel Page2 { get; set; }

    public MultiPageViewModel()
    {
        Page1 = new Page1ViewModel();
        Page2 = new Page2ViewModel();

        Page2.AddNewCommand = new Command(Page1.AddCommand);
    }
}

第1页:

<UserControl x:Class="MiscSamples.MultiPageMVVM.Page1"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <ItemsControl ItemsSource="{Binding Commands}">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <WrapPanel IsItemsHost="True"/>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <Button Command="{Binding}" Content="Click Me!"
                        Margin="2"/>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
</UserControl>

代码背后:

public partial class Page1 : UserControl
{
    public Page1()
    {
        InitializeComponent();
    }
}

2页:

<UserControl x:Class="MiscSamples.MultiPageMVVM.Page2"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Button Content="Add New Command (I Mean Button)"
            VerticalAlignment="Center" HorizontalAlignment="Center"
            Command="{Binding AddNewCommand}"/>
</UserControl>

代码背后:

public partial class Page2 : UserControl
{
    public Page2()
    {
        InitializeComponent();
    }
}

视图模型:

public class Page2ViewModel
{
    public Command AddNewCommand { get; set; }
}

命令类(可在大多数MVVM框架上找到)

//Dead-simple implementation of ICommand
    //Serves as an abstraction of Actions performed by the user via interaction with the UI (for instance, Button Click)
    public class Command : ICommand
    {
        public Action Action { get; set; }

        public void Execute(object parameter)
        {
            if (Action != null)
                Action();
        }

        public bool CanExecute(object parameter)
        {
            return IsEnabled;
        }

        private bool _isEnabled = true;
        public bool IsEnabled
        {
            get { return _isEnabled; }
            set
            {
                _isEnabled = value;
                if (CanExecuteChanged != null)
                    CanExecuteChanged(this, EventArgs.Empty);
            }
        }

        public event EventHandler CanExecuteChanged;

        public Command(Action action)
        {
            Action = action;
        }
    }

    public class Command<T>: ICommand
    {
        public Action<T> Action { get; set; }

        public void Execute(object parameter)
        {
            if (Action != null && parameter is T)
                Action((T)parameter);
        }

        public bool CanExecute(object parameter)
        {
            return IsEnabled;
        }

        private bool _isEnabled;
        public bool IsEnabled
        {
            get { return _isEnabled; }
            set
            {
                _isEnabled = value;
                if (CanExecuteChanged != null)
                    CanExecuteChanged(this, EventArgs.Empty);
            }
        }

        public event EventHandler CanExecuteChanged;

        public Command(Action<T> action)
        {
            Action = action;
        }
    }

结果:

enter image description here

现在,解释所有这些混乱:

首先,您必须leave behind the traditional mentality 在代码中操作UI元素,并拥抱MVVM

WPF具有非常强大的DataBinding能力,在古代恐龙框架中完全没有。

注意我是如何使用可重用的Command类(它是大多数MVVM框架的基本部分)来表示Page1ViewModel中的按钮。然后将Command的这些实例添加到ObservableCollectionDataTemplate会在向其添加或删除元素时通知WPF,因此Binding会自动更新UI。 / p>

然后,Page1ItemTemplate定义的ItemsControl {{3}}用于“呈现”ObservableCollection内的每个项目。

当我说WPF需要一种非常不同的心态来处理时,这就是我所指的。这是WPF中一切的默认方法。您几乎从不需要在过程代码中引用/创建/操作UI元素。这就是XAML的用途。

另请注意,这可以通过对ViewModel两个Page使用相同的{{1}}进行简化,但我故意将它们分开,只是为了向您展示这种情况,即您有不同的ViewModel与之通信彼此直接。

如果您有任何疑问,请告诉我。