繁体   English   中英

使用不同的 DataContexts 在 WPF 元素中绑定不同的属性

[英]Binding different properties within WPF element using different DataContexts

我有这部分代码用于更新 C# WPF 中文本框中的数字显示。

CS:

namespace BindTest
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public BindInt x1 = new BindInt(0);

        public MainWindow()
        {
            InitializeComponent();
            Test1_Tbox.DataContext = x1;
        }

        private void Up_Btn_Click(object sender, RoutedEventArgs e)
        {
            x1.Number += 1;
        }

        private void Dn_Btn_Click(object sender, RoutedEventArgs e)
        {
            x1.Number -= 1;
        }
    }

    public class BindInt : INotifyPropertyChanged
    {
        // integer class with property change notification for binding

        private int number;

        public event PropertyChangedEventHandler PropertyChanged;

        public BindInt()
        {
            number = 0;
            OnPropertyChanged("Number");
        }

        public BindInt(int Val)
        {
            number = Val;
            OnPropertyChanged("Number");
        }

        public int Number
        {
            get { return this.number; }
            set
            {
                if (number != value)
                {
                    number = value;
                    OnPropertyChanged(nameof(Number));
                }
            }
        }

        protected void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
}

XAML:

<Window x:Class="BindTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:BindTest"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <TextBox x:Name="Test1_Tbox" 
                 HorizontalAlignment="Left" 
                 Margin="10,10,0,0" 
                 Text="{Binding Number, Mode=OneWay, StringFormat=\{0:D\}}" 
                 TextWrapping="Wrap" 
                 VerticalAlignment="Top" Width="120"/>

        <Button x:Name="Up_Btn" Click="Up_Btn_Click" Content="Up" HorizontalAlignment="Left" Margin="550,124,0,0" VerticalAlignment="Top" Width="50" Height="20"/>
        <Button x:Name="Dn_Btn" Click="Dn_Btn_Click" Content="Down" HorizontalAlignment="Left" Margin="550,164,0,0" VerticalAlignment="Top" Width="50" Height="20"/>

    </Grid>
</Window>

所以现在我可以在单击按钮时看到显示的值更新。

在我的实际应用程序中,我需要执行以下操作:

  • 显示值如上。
  • 使多个控件可见或隐藏以及启用或禁用。

目前,我只是直接写入每个控件的可见性属性,但由于控件的数量,这变得笨拙。 我正在寻找的是一种方法:

  • 将文本值绑定到一个属性(例如上例中的 x1.Number)。
  • 将可见性绑定到另一个属性。
  • 可能将 Enabled 绑定到另一个属性。

我尝试了许多绑定组合,但似乎唯一对我有用的就是上面的安排 - 在代码隐藏中设置 DataContext 并绑定到 x1 的 Number 属性。

有没有一种很好的通用方法来以这种方式绑定? 如果我可以将 DataContext 设置为 MainWindow class 然后绑定到例如 x1.Number,那么这可能会满足我的需要。

使用 MVVM 模式从 MainWindow 中删除所有逻辑

创建新的 class 可观察对象

public class ObservableObject : INotifyPropertyChanged
{

    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

通过扩展 ICommand 创建名为 UpdateTextCommand 的命令并在那里处理您的逻辑

public class UpdateTextCommand : ICommand
{
    public event EventHandler CanExecuteChanged;
    private MainViewModel Mainviewmodel;
    public UpdateTextCommand(MainViewModel mainviewmodel)
    {
       Mainviewmodel = mainviewmodel
    }

    public bool CanExecute(object parameter)
    {
        return true;
    }

    public void Execute(object parameter)
    {
       Mainviewmodel.SomeText = "Changed Text";
       //Visibility.Collapsed hides controls
       Mainviewmodel.Visibility = Visibility.Collapsed
    }
}

创建其他 class MainViewModel 扩展 Observableobject

public class MainViewModel : Observableobject
{
    public MainViewModel()
    {
        UpdateTextCommand= new UpdateTextCommand(this);
    }
    public ICommand UpdateTextCommand{ get; }

    private Visibility _visibility;

    public Visibility Visibility
    {
        get { return _visibility; }
        set { _visibility= value;
            OnPropertyChanged(nameof(Visibility));
        }
    }

    private string _sometext;

    public string SomeText
    {
        get { return _sometext; }
        set
        {
            _sometext= value;
            OnPropertyChanged(nameof(SomeText));
        }
    }
}

现在在 MainWindow 构造函数中添加绑定

    public MainWindow()
    {
        DataContext = MainViewModel;
        InitializeComponent();
    }

在 Xaml 中只需添加绑定到 MainViewModel 属性

 <TextBox x:Name="Test1_Tbox" 
             HorizontalAlignment="Left" 
             Margin="10,10,0,0" 
             Text="{Binding SomeText, StringFormat=\{0:D\}}" 
             Visibility = "{Binding Visibility}"
             TextWrapping="Wrap" 
             VerticalAlignment="Top" Width="120"/>
<Button x:Name="Up_Btn" Command={Binding UpdateTextCommand}  Content="Up" HorizontalAlignment="Left" Margin="550,124,0,0" VerticalAlignment="Top" Width="50" Height="20"/>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM