从c#中单独的类绑定wpf中的文本框

本文关键字:wpf 文本 绑定 单独 | 更新日期: 2023-09-27 18:05:19

新的WPF尝试实现一个简单的文本框绑定。需要一些帮助才能使它运行。

XAML

<Window x:Class="WPFModel.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:src="clr-namespace:WPFModel"
    DataContext="{Binding RelativeSource={RelativeSource Self}}"
    mc:Ignorable="d"
    Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <src:Test x:Key="myDataSource" TextBoxName="Text Init" />
    </Window.Resources>
<Grid>
    <TextBox x:Name="S1" Text = "{Binding Source={StaticResource myDataSource}, Path=TextBoxName, UpdateSourceTrigger= PropertyChanged, Mode = TwoWay}" HorizontalAlignment="Left" Height="50" Margin="160,165,0,0" VerticalAlignment="Top" Width="185"/>
</Grid>

主窗口

namespace WPFModel
{
    public partial class MainWindow : Window
    {
        Test tb = new Test();
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = this;
            tb.Drawtext();
        }
    }
}

代码后面

namespace WPFModel
{
    public class Test : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        private string value1;
        public string TextBoxName
        {
            get { return value1; }
            set
            {
                value1 = value;
                RaisePropertyChanged("TextBoxName");
            }
        }
        protected void RaisePropertyChanged(string propertyName)
        {
            var handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }
        public void Drawtext()
        {
            TextBoxName = "Textbox text";
        }
    }
}

从c#中单独的类绑定wpf中的文本框

您将Window的数据上下文设置为自身,而不是将其设置为Test对象的实例:

this.DataContext = tb;

然后你可以将文本框的绑定设置为数据上下文对象的属性:

... Text="{Binding TextBoxName, UpdateSourceTrigger= PropertyChanged, Mode = TwoWay}" ...

您设置了多次DataContext。一次在窗口(DataContext="{Binding RelativeSource={RelativeSource Self}}")的属性中的XAML标记中,一次在窗口(this.DataContext = this;)的代码后置构造函数中。在这两种情况下,您都没有将DataContext设置为Test的实例。

您还创建了Test的两个实例。一次在作为资源的XAML标记中(<src:Test x:Key="myDataSource" TextBoxName="Text Init" />),另一次在代码隐藏中(Test tb = new Test();)。然后将文本框绑定到Test的资源实例。由于您在代码隐藏实例上调用DrawText(),窗口中的文本框永远不会更新。

相反,你想做的是有一个Test的实例作为你的窗口的DataContext。由于理想情况下,我们希望在MVVM中保持代码隐藏文件(您正在调用主窗口)中的代码量最少,因此最好的方法是如下面的示例所示。你还会看到你可以使用Commands而不是OnClick处理程序来调用视图模型中的操作。如果您不熟悉RelayCommand,那么请查看这里的简单实现

XAML

<Window x:Class="WPFModel.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:src="clr-namespace:WPFModel"
    mc:Ignorable="d"
    Title="MainWindow" Height="350" Width="525">
    <Window.DataContext>
        <src:Test />
    </Window.DataContext>
    <StackPanel>
        <TextBox x:Name="S1" Text = "{Binding TextBoxName}" HorizontalAlignment="Left" Height="50" Margin="160,165,0,0" VerticalAlignment="Top" Width="185"/>
        <Button Content="Click Me!" Command={Binding DrawTextCommand} />
    </StackPanel>
</Window>

namespace WPFModel
{
    public class Test : INotifyPropertyChanged
    {
        public ICommand DrawTextCommand { get; private set; }
        public event PropertyChangedEventHandler PropertyChanged;
        private string value1;
        public string TextBoxName
        {
            get { return value1; }
            set
            {
                value1 = value;
                RaisePropertyChanged("TextBoxName");
            }
        }
        public Test()
        {
            this.DrawTextCommand = new RelayCommand(DrawText);
        }
        protected void RaisePropertyChanged(string propertyName)
        {
            var handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }
        public void Drawtext()
        {
            TextBoxName = "Textbox text";
        }
    }
}

主窗口代码隐藏

namespace WPFModel
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
    }
}