3

私は VB から C# に移行していますが、開発しているプログラムは GUI ベースのアプリケーションに大きく依存しているため、WPF が最適な選択肢であると判断しました。しかし、VB の単純なタスクを C# コードで動作させようとすると、C# によって多くの頭痛、混乱、フラストレーションが生じます。VB では、これを非常に簡単に機能させることができます。しかし、C# では、数え切れないほどの時間 (現在では数日) をコードの検索と操作に費やした後でも、これを機能させる方法についてはまだ賢明ではありません。

私のシナリオ:

  • 2 つの xaml ページがあります。
  • 最初の xaml ページにはラップパネルがあります。
  • 2 番目の xaml ページには、新しいボタンを作成し、それを xaml ページ 1 のラップパネルに追加するボタンがあります。

page1.xaml.cs で以下のコードを使用すると、wrappanel に新しいボタンを簡単に追加できます。

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

また、page2 から page1 にあるメソッドを呼び出してボタンを作成しようとしましたが、新しいボタンがラップパネルに表示されません!?

途中で助けてくれる助けと、おそらく簡単なコード例をいただければ幸いです。

4

1 に答える 1

7

わかりました、私UserControlは s の代わりに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機能があります。

Page1ViewModel のボタンを表すために、再利用可能なCommandクラス (ほとんどの MVVM フレームワークの基本部分のようなもの) をどのように使用しているかに注意してください。のこれらのインスタンスはCommandに追加されObservableCollection、要素が追加または削除されたときに WPF に通知されるため、UI は によって自動的に更新されますBinding

次に、forDataTemplateとして定義されたを使用して、 内の各アイテムを「レンダリング」します。ItemTemplateItemsControlPage1ObservableCollection

これは、WPF で作業するにはまったく異なる考え方が必要であると私が言うときに言及するものです。これは、WPF のすべてに対するデフォルトのアプローチです。手続き型コードで UI 要素を参照/作成/操作する必要はほとんどありません。それが XAML の目的です。

ViewModelまた、これは両方の s に同じものを使用することで大幅に簡略化できることに注意してPageください。ただし、異なる ViewModel が互いに直接通信しているこのケースを示すために、意図的にそれらを分けておきました。

ご不明な点がございましたらお知らせください。

于 2013-05-03T21:15:07.980 に答える