UserControl使用自己的数据

时间:2013-06-04 15:16:47

标签: c# wpf binding user-controls

我有一个带有TextBox(Y)和Button的用户控件,在我的MainWindow(Y)中有另一个TextBox。当您按下按钮时,会弹出一条消息并向我们显示产品X * Y。

现在,如果我只是简单地通过XAML插入另一个,因为它绑定到UserControl的一些数据,原始和刚刚添加的显示相同(因为正如我所说的TextBox.Text绑定)。

我想要的是知道如何扩展它并在我的MainWindow中添加几个UserControl,因此我可以在每个UserControl中键入不同的值,然后按下按钮,看看每个产品的数量。

enter image description here

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,而是一种生成它们的方法,也许只需要一个“创建UserControl!”的Button。感谢。

(感谢sevenate帮我编写代码)

1 个答案:

答案 0 :(得分: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();
    }
}

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");    
        }
    }
}

UserControlViewModel:

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

    public Command PressMeCommand { get; set; }
}

命令类(为避免使用不属于的Click事件处理程序):

//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;
    }
}

结果:

enter image description here