3

我正在从 VB 迁移到 C#,并决定 WPF 对我来说是最佳选择,因为我一直在开发的程序是高度依赖于 GUI 的应用程序。然而,当我试图让 VB 中的简单任务在 C# 代码中工作时,C# 让我感到头疼、困惑和沮丧。在 VB 中,我可以很容易地完成这项工作。但是在 C# 中,在花费了无数小时(现在是几天)搜索和玩代码之后,我仍然不知道如何让它工作。

我的场景:

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

在 page1.xaml.cs 中使用以下代码时,我可以轻松地向包装面板添加一个新按钮:

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

我还尝试从 page2 调用位于 page1 中的方法来创建按钮,但新按钮未显示在包装面板中!?

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

4

1 回答 1

7

好的,我使用UserControls 而不是Pages 将它们保存在一个窗口中。由于您没有发布任何 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;
        }
    }

结果:

在此处输入图像描述

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

首先,你必须摒弃在代码中操作 UI 元素的传统心态,拥抱MVVM

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

请注意我如何使用可重用Command类(这是大多数 MVVM 框架的基本部分)来表示 Page1ViewModel 中的按钮。然后将这些实例Command添加到 中ObservableCollection,当元素添加或删除时,它会通知 WPF,因此 UI 会由Binding.

然后,DataTemplate定义为ItemTemplateinItemsControlPage1用于“渲染” 中的每个项目ObservableCollection

当我说 WPF 需要一种完全不同的思维方式来工作时,这就是我所指的。这是 WPF 中一切的默认方法。您几乎不需要在程序代码中引用/创建/操作 UI 元素。这就是 XAML 的用途。

另请注意,这可以通过ViewModel对两个Pages 使用相同的方式来简化很多,但我故意将它们分开只是为了向您展示这种情况,即您有不同的 ViewModel 直接相互通信。

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

于 2013-05-03T21:15:07.980 回答