我正在从VB迁移到C#,并认为WPF对我来说是最好的选择,因为我一直在开发的程序是基于GUI的高度依赖的应用程序。但是,在尝试获取VB中用于C#代码的简单任务时,C#给我带来了很多麻烦,困惑和沮丧。在VB中,我可以很容易地使用它。但是在C#中,在花了无数个小时(现在几天)搜索和玩代码之后,我仍然不知道如何让它工作。
我的情景:
使用page1.xaml.cs中的以下代码时,我可以轻松地向wrappanel添加一个新按钮:
Button New_Button = new Button();
My_WrapPanel.Children.Add(New_Button);
我也试过调用第2页第1页的方法来创建按钮,但新的按钮没有显示在wrappanel中??
我真的很感激一些帮助,可能还有一个简单的代码示例来帮助我。
答案 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;
}
}
结果:
现在,解释所有这些混乱:
首先,您必须leave behind the traditional mentality 在代码中操作UI元素,并拥抱MVVM。
WPF具有非常强大的DataBinding能力,在古代恐龙框架中完全没有。
注意我是如何使用可重用的Command
类(它是大多数MVVM框架的基本部分)来表示Page1ViewModel中的按钮。然后将Command
的这些实例添加到ObservableCollection
,DataTemplate
会在向其添加或删除元素时通知WPF,因此Binding
会自动更新UI。 / p>
然后,Page1
中ItemTemplate
定义的ItemsControl
{{3}}用于“呈现”ObservableCollection
内的每个项目。
当我说WPF需要一种非常不同的心态来处理时,这就是我所指的。这是WPF中一切的默认方法。您几乎从不需要在过程代码中引用/创建/操作UI元素。这就是XAML的用途。
另请注意,这可以通过对ViewModel
两个Page
使用相同的{{1}}进行简化,但我故意将它们分开,只是为了向您展示这种情况,即您有不同的ViewModel与之通信彼此直接。
如果您有任何疑问,请告诉我。