2

TextBox (Y) と Button を持つユーザー コントロールがあり、MainWindow(Y) には別の TextBox があります。ボタンを押すと、メッセージがポップアップ表示され、製品 X*Y が表示されます。

現在、UserControl、元のデータ、および追加したばかりのデータの両方にバインドされているため、XAML を介して別のデータを挿入するだけで同じように表示されます (TextBox.Text がバインドされていると言ったため)。

私が知りたいのは、これを拡張して MainWindow に複数の UserControl を追加する方法を知りたいので、各 UserControl に異なる値を入力してからボタンを押して、各製品の価格を確認することです。

ここに画像の説明を入力

RootViewMode.cs

public class RootViewModel : INotifyPropertyChanged
    {
        #region Implementation of INotifyPropertyChanged

        private double _x;
        private double _y;

        public double X
        {
            get { return _x; }
            set
            {
                _x = value;
                OnPropertyChanged("X");
            }
        }

        public double Y
        {
            get { return _y; }
            set
            {
                _y = value;
                OnPropertyChanged("Y");
            }
        }

        public double XY
        {
            get { return _x * _y; }
        }
    }

UserControl1.xaml

  <StackPanel>
            <Label Content="Y:" />
            <TextBox Text="{Binding Path=Y, UpdateSourceTrigger=PropertyChanged, FallbackValue=1}" Margin="5" />
            <Button Content="Press me" Click="OnButtonClick" />
        </StackPanel>

UserControl1.xaml.cs

private void OnButtonClick(object sender, RoutedEventArgs e)
    {
        var viewModel = (RootViewModel)DataContext;
        var resultMessage = string.Format("{0} * {1} = {2}", viewModel.X, viewModel.Y, viewModel.XY);

        MessageBox.Show(resultMessage, "X * Y");
    }

MainWindow.xaml

 <StackPanel>
        <Label Content="X:" />
        <TextBox Text="{Binding Path=X, UpdateSourceTrigger=PropertyChanged}" Margin="5" Height="24" />
        <WpfApplication22:UserControl1  Margin="5" />
        <WpfApplication22:UserControl1  Margin="5" />
    </StackPanel>

もちろん、この方法で UserControl を挿入すると、望ましくない結果が得られます。UserControl ごとに新しい RootViemModel を作成する必要があると思いますが、これは動的に行う必要があります。2 つの UserControl だけではなく、「Create UserControl!」というボタンを使用してそれらを生成する方法が必要です。ありがとう。

(コードを手伝ってくれたsevenateに感謝します)

4

1 に答える 1

3

そのためには次のものが必要ItemsControlです。

<Window x:Class="MiscSamples.UserControlItemsControl"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="UserControlItemsControl" Height="300" Width="300">
    <DockPanel>
        <StackPanel DockPanel.Dock="Top">
            <Label Content="X:"/>
            <TextBox Text="{Binding X}"/>
            <Button Content="Add User Control" Command="{Binding AddUserControlCommand}"/>
        </StackPanel>

        <ItemsControl ItemsSource="{Binding Children}">
            <ItemsControl.Template>
                <ControlTemplate>
                    <ScrollViewer CanContentScroll="True">
                        <ItemsPresenter/>
                    </ScrollViewer>
                </ControlTemplate>
            </ItemsControl.Template>
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <!-- Here you can place your local:UserControl. I just thrown the UI elements -->
                    <GroupBox Header="User Control">
                        <StackPanel>
                            <Label Content="Y:"/>
                            <TextBox Text="{Binding Y}"/>
                            <Button Content="Press Me!" Command="{Binding PressMeCommand}"/>
                        </StackPanel>
                    </GroupBox>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </DockPanel>
</Window>

コードビハインド:

public partial class UserControlItemsControl : Window
{
    public UserControlItemsControl()
    {
        InitializeComponent();
        DataContext = new RootViewModel();
    }
}

ルートビューモデル:

public class RootViewModel: PropertyChangedBase
{
    private double _x;
    public double X
    {
        get { return _x; }
        set
        {
            _x = value;
            OnPropertyChanged("X");
        }
    }

    public ObservableCollection<UserControlViewModel> Children { get; set; }
    public Command AddUserControlCommand { get; set; }

    public RootViewModel()
    {
        Children = new ObservableCollection<UserControlViewModel>();
        AddUserControlCommand = new Command(AddUserControl);
    }

    private void AddUserControl()
    {
        var child = new UserControlViewModel();
        child.PressMeCommand = new Command(() => OnUserControlPressed(child));
        Children.Add(child);
    }

    private void OnUserControlPressed(UserControlViewModel item)
    {
        if (item != null)
        {
            var xy = X * item.Y;
            var resultMessage = string.Format("{0} * {1} = {2}", X, item.Y, xy);

            MessageBox.Show(resultMessage, "X * Y");    
        }
    }
}

ユーザー コントロール ビュー モデル:

public class UserControlViewModel:PropertyChangedBase
{
    private double _y;
    public double Y
    {
        get { return _y; }
        set
        {
            _y = value;
            OnPropertyChanged("Y");
        }
    }

    public Command PressMeCommand { 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;
    }
}

結果:

ここに画像の説明を入力

于 2013-06-04T16:21:03.783 に答える