【问题标题】:Multibinding between 2 usercontrols2个用户控件之间的多重绑定
【发布时间】:2013-08-08 12:45:09
【问题描述】:

我有 2 个用户控件。 用户控件 1:具有添加、编辑、删除、保存和撤消等按钮的菜单栏。 用户控件 2:是用户可以在文本框和密码框中输入文本的屏幕

但是当我想要保存时,我习惯于执行以下操作,因为我只有 1 个用户控件,其中包含按钮和所有内容,而不是菜单栏和详细屏幕分开:

     <Button Style="{DynamicResource SaveButton}" Command="{Binding Path=SaveCommand}">
                <Button.CommandParameter>
                    <MultiBinding Converter="{StaticResource pwConverter}">
                        <Binding ElementName="txtPassword" />
                        <Binding ElementName="txtRepeatPassword" />
                    </MultiBinding>
                </Button.CommandParameter>
            </Button>

但现在元素名称“txtPassword”和“txtRepeatPassword”不存在于该范围内。 当我单击保存按钮时,这是我的 SaveCommand。它接收这 2 个参数,因此我可以检查 2 个密码是否相同以及类似的东西。

    private void SaveUserExecute(object passwords)
    {
        try
        {
            var passwordvalues       = (object[])passwords;
            PasswordBox passwordBox1 = (PasswordBox)passwordvalues[0];
            PasswordBox passwordBox2 = (PasswordBox)passwordvalues[1];
       ...

关于如何解决这个问题的任何想法?

【问题讨论】:

  • 您能否将整个用户控件 2 作为参数发送并更改您的转换器以从中提取密码框?
  • 我不知道该怎么做,就像你在我的实现中所说的那样。但我自己提供了一个对我有用的答案。还是谢谢!
  • 这有点类似于你的答案,也有点像黑客。我总是害怕在 WPF 中使用密码框,因为您无法将它们绑定到任何东西,并且需要这些迂回的黑客来连接。

标签: c# wpf multibinding


【解决方案1】:

因为我的 2 个用户控件共享相同的 DataContext,所以我创建了 2 个属性来代表我的 PasswordBox。当我初始化该视图时,我执行了以下操作:

    public InputUserView()
    {
        InitializeComponent();
        this.DataContext = InputUserViewModel.Instance;
        InputUserViewModel.Instance.PasswordBox1 = txtPassword;
        InputUserViewModel.Instance.PasswordBox2 = txtRepeatPassword;
    }

所以现在我的视图模型知道这两个密码框了。我认为它并不是那么好,但它对我有用,我可以忍受它

【讨论】:

    【解决方案2】:

    如果您使用 MVVM 模式,这很容易。您可以拥有一个 ViewModel,它可以作为每个用户控件和主窗口的 DataContext。然后只需绑定到每个属性上的属性。

    下面是一个 ViewModel 示例,它具有由我们可以绑定到的属性公开的字段:

    public class ViewModel : INotifyPropertyChanged
    {
        private readonly Command _command;
    
        public Command Command
        {
            get { return _command; }
        }
    
        public ViewModel()
        {
            _command = new Command(this);
        }
    
        private string _textBoxOnUserControlOne;
        private string _textBoxOnUserControlTwo;
    
        public string TextBoxOnUserControlOne
        {
            get { return _textBoxOnUserControlOne; }
            set
            {
                if (value == _textBoxOnUserControlOne) return;
                _textBoxOnUserControlOne = value;
                OnPropertyChanged("TextBoxOnUserControlOne");
            }
        }
    
        public string TextBoxOnUserControlTwo
        {
            get { return _textBoxOnUserControlTwo; }
            set
            {
                if (value == _textBoxOnUserControlTwo) return;
                _textBoxOnUserControlTwo = value;
                OnPropertyChanged("TextBoxOnUserControlTwo");
            }
        }
    
        public event PropertyChangedEventHandler PropertyChanged;
    
        [NotifyPropertyChangedInvocator]
        protected virtual void OnPropertyChanged(string propertyName)
        {
            var handler = PropertyChanged;
            if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    

    这是命令类,我将在其中使用这两个属性:

    public class Command : ICommand
    {
        private readonly ViewModel _viewModel;
    
        public Command(ViewModel viewModel)
        {
            _viewModel = viewModel;
        }
    
        public void Execute(object parameter)
        {
            var dataOnControlOne = _viewModel.TextBoxOnUserControlOne;
            var dataOnControlTwo = _viewModel.TextBoxOnUserControlTwo;
    
            //Use these values
        }
    
        public bool CanExecute(object parameter)
        {
            return true;
        }
    
        public event EventHandler CanExecuteChanged;
    }
    

    现在,这是我的第一个用户控件 1,它绑定到我的 ViewModel 上的一个字段,注意 DataContext:

    <UserControl ... DataContext="{StaticResource ViewModel}">
        <Grid>
            <TextBox Height="23" HorizontalAlignment="Left" Text="{Binding TextBoxOnUserControlOne}" Margin="12,12,0,0" Name="textBox1" VerticalAlignment="Top" Width="120" />
        </Grid>
    </UserControl>
    

    这是第二个具有相同 DataContext 的 UserControl,文本框绑定到不同的属性:

    <UserControl ... DataContext="{StaticResource ViewModel}">
        <Grid>
            <TextBox Height="23" HorizontalAlignment="Left" Text="{Binding TextBoxOnUserControlTwo}" Margin="12,12,0,0" Name="textBox1" VerticalAlignment="Top" Width="120" />
        </Grid>
    </UserControl>
    

    这是我的主窗口,其中包含这两个用户控件,以及绑定到我的命令类的按钮:

    <Window ... DataContext="{StaticResource ViewModel}">
        <Grid>
            <my:UserControl1 HorizontalAlignment="Left" Margin="160,69,0,0" x:Name="userControl11" VerticalAlignment="Top" Height="47" Width="155" />
            <my:UserControl2 HorizontalAlignment="Left" Margin="160,132,0,0" x:Name="userControl12" VerticalAlignment="Top" Height="48" Width="158" />
            <Button Content="Button" Command="{Binding Command}" Height="23" HorizontalAlignment="Left" Margin="199,198,0,0" Name="button1" VerticalAlignment="Top" Width="75" />
        </Grid>
    </Window>
    

    最后是我的 App.Xaml 类,将所有内容粘合在一起:

    <Application ...>
        <Application.Resources>
             <wpfApplication4:ViewModel x:Key="ViewModel"/>
        </Application.Resources>
    </Application>
    

    在这里,我们有单独的用户控件,并且字段绑定到一个视图模型上的属性。此视图模型将自身传递到命令类,然后该命令类可以访问单独用户控件上的文本框所绑定的属性,并在按下按钮时使用它们。我希望这会有所帮助!

    【讨论】:

    • 是的,我知道您的实施。仅使用文本框很容易,但在我的情况下,也有密码框。而且我无法将密码框中的密码绑定到属性,就像您从文本框中执行文本一样......但我没有很好地提到这个问题是专门针对密码框的。我的错,对不起
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多