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