C# 如何在另一个类中将控件动态添加到WrapPanel?

C# 如何在另一个类中将控件动态添加到WrapPanel?,c#,.net,wpf,C#,.net,Wpf,我正在从VB迁移到C#,并决定WPF将是我的最佳选择,因为我开发的程序是高度依赖GUI的应用程序。然而,当我试图让VB中的简单任务在C代码中工作时,C语言给我带来了很多麻烦、困惑和挫折。在VB中,我可以很容易地实现这一点。但是在C#中,在花了无数个小时(现在是几天)搜索和玩代码之后,我仍然不知道如何让它工作 我的设想: 我有2个xaml页面 第一个xaml页面有一个wrappanel 第二个xaml页面有一个按钮,该按钮将创建一个新按钮并将其添加到xaml第1页的包装中 使用page1.xa

我正在从VB迁移到C#,并决定WPF将是我的最佳选择,因为我开发的程序是高度依赖GUI的应用程序。然而,当我试图让VB中的简单任务在C代码中工作时,C语言给我带来了很多麻烦、困惑和挫折。在VB中,我可以很容易地实现这一点。但是在C#中,在花了无数个小时(现在是几天)搜索和玩代码之后,我仍然不知道如何让它工作

我的设想:

  • 我有2个xaml页面
  • 第一个xaml页面有一个wrappanel
  • 第二个xaml页面有一个按钮,该按钮将创建一个新按钮并将其添加到xaml第1页的包装中
使用page1.xaml.cs中的以下代码时,我可以轻松地向wrappanel添加一个新按钮:

Button New_Button = new Button();
My_WrapPanel.Children.Add(New_Button);
我还尝试从第2页调用位于第1页的方法来创建按钮,但新按钮没有显示在wrappanel


我非常感谢您的帮助,可能还有一个简单的代码示例可以帮助我。

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

MultiPageSample.xaml(“主窗口”):

视图模型:

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);
    }
}
public class Page2ViewModel
{
    public Command AddNewCommand { get; set; }
}
第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>
第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 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);
    }
}
public class Page2ViewModel
{
    public Command AddNewCommand { get; set; }
}
命令类(可以在大多数MVVM框架上找到)

//ICommand的简单实现
//作为用户通过与UI交互执行的操作的抽象(例如,按钮单击)
公共类命令:ICommand
{
公共操作动作{get;set;}
public void Execute(对象参数)
{
如果(操作!=null)
动作();
}
公共布尔CanExecute(对象参数)
{
返回被禁止;
}
private bool _isEnabled=true;
公共场所被禁止
{
获取{return}
设置
{
_isEnabled=值;
如果(CanExecuteChanged!=null)
CanExecuteChanged(此为EventArgs.Empty);
}
}
公共事件处理程序CanExecuteChanged;
公共命令(行动)
{
行动=行动;
}
}
公共类命令:ICommand
{
公共操作动作{get;set;}
public void Execute(对象参数)
{
if(Action!=null&&参数为T)
作用((T)参数);
}
公共布尔CanExecute(对象参数)
{
返回被禁止;
}
私人住宅已启用;
公共场所被禁止
{
获取{return}
设置
{
_isEnabled=值;
如果(CanExecuteChanged!=null)
CanExecuteChanged(此为EventArgs.Empty);
}
}
公共事件处理程序CanExecuteChanged;
公共命令(行动)
{
行动=行动;
}
}
结果:

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

首先,您必须了解如何在代码中操作UI元素,并接受它们

WPF具有非常强大的功能,这在古代恐龙框架中是完全不存在的

注意我是如何使用可重用的
命令
类(这是大多数MVVM框架的基本部分)来表示Page1ViewModel中的按钮的。然后将
命令的这些实例添加到,当元素被添加或删除到WPF时,WPF会通知该实例,因此,
绑定会自动更新UI

然后,在
Page1
中定义为的用于“呈现”
可观察集合中的每个项目

这就是我所说的WPF需要一种完全不同的思维方式。这是WPF中所有内容的默认方法。您几乎从来都不需要在过程代码中引用/创建/操作UI元素。这就是XAML的用途

还要注意的是,对于两个
页面
使用相同的
ViewModel
可以大大简化这一过程,但我故意将它们分开,只是为了向您展示这样一种情况,即不同的ViewModel直接相互通信


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

WPF本身就是一个非常复杂的框架,它需要一种非常特殊的思维方式(MVVM),这与古代的传统UI框架非常不同。我的建议是,在深入WPF之前,先熟悉C#本身(可能是使用一些winforms或控制台应用程序?@HighCore哇,我的眼睛骗过我了吗?你在推荐WinForms?@LarsTech中的一些东西只是为了让初学者习惯代码,这是垃圾真正有价值的东西。非常感谢@HighCore!你帮我指引了正确的方向。感谢您花时间精心制作了如此详细的回复。
public partial class Page2 : UserControl
{
    public Page2()
    {
        InitializeComponent();
    }
}
public class Page2ViewModel
{
    public Command AddNewCommand { get; set; }
}
//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;
        }
    }