wpf 在 XAML 中设置元素的 DataContext?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25267070/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 12:19:52  来源:igfitidea点击:

Setting DataContext of elements inside XAML?

wpf

提问by Foysal94

Hi am trying to get the hang of binding.

嗨,我正试图掌握绑定的窍门。

The XAML code:

XAML 代码:

<Window x:Class="WPF_SandBox.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

        Title="MainWindow" Height="350" Width="525">
    <StackPanel x:Name="stackPanel">
        <TextBox x:Name="textBox_FirstName" Width="200" Margin="0,100,0,0" Text="{Binding Path=FirstName, UpdateSourceTrigger=PropertyChanged}"  />
        <TextBox x:Name="textBox_LastName" Width="200" Margin="0,10,0,0" Text="{Binding Path=LastName, UpdateSourceTrigger=PropertyChanged}" />
        <TextBlock x:Name="textBlock_FullName"  Background="LightBlue" Width="200" Margin="0,10,0,0" Text="{Binding Path=FullName, UpdateSourceTrigger=PropertyChanged}"  />
    </StackPanel>
</Window>

The C# code:

C#代码:

public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            Person person = new Person { FirstName = "Matt", LastName = "Smith" };
            stackPanel.DataContext = person;

        }
    }

    public class Person : INotifyPropertyChanged
    {
        string firstName;
        string lastName;

        public string FirstName
        {
            get
            { 
                return firstName;
            }
            set
            {
                firstName = value;
                OnPropertyChanged("FirstName");
                OnPropertyChanged("FullName");
            }
        }

        public string LastName
        {
            get { return lastName; }
            set
            {
                lastName = value;
                OnPropertyChanged("LastName");
                OnPropertyChanged("FullName");
            }
        }

        public string FullName
        {
            get
            {
                return String.Format("{0}, {1}",lastName,firstName);
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

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

When started, a window with 2 textboxes and 1 textblock shows. Inside the window constructor, I have created an instance of person and assigned the DataContext of the stackPanel to this instance. The first textbox is binded to the FirstName property of the Person class, the second TextBox is binded to the LastName property and the final TextBlock just prints the LastName property followed by the FirstName properties. As I said earlier, I set the DataContext of the stackPanel inside the C# code. How can I set it instead inside the XAML? For example:

启动时,会显示一个包含 2 个文本框和 1 个文本块的窗口。在窗口构造函数中,我创建了一个 person 实例并将 stackPanel 的 DataContext 分配给了这个实例。第一个文本框绑定到 Person 类的 FirstName 属性,第二个 TextBox 绑定到 LastName 属性,最后一个 TextBlock 只打印 LastName 属性,然后是 FirstName 属性。正如我之前所说,我在 C# 代码中设置了 stackPanel 的 DataContext。如何在 XAML 中设置它?例如:

<StackPanel x:Name="stackPanel" DataContext="person">
        <TextBox x:Name="textBox_FirstName" Width="200" Margin="0,100,0,0" Text="{Binding Path=FirstName, UpdateSourceTrigger=PropertyChanged}"  />
        <TextBox x:Name="textBox_LastName" Width="200" Margin="0,10,0,0" Text="{Binding Path=LastName, UpdateSourceTrigger=PropertyChanged}" />
        <TextBlock x:Name="textBlock_FullName"  Background="LightBlue" Width="200" Margin="0,10,0,0" Text="{Binding Path=FullName, UpdateSourceTrigger=PropertyChanged}"  />
    </StackPanel>

This doesn't work, but as you can see I am trying to set the DataContext of the stackPanel inside the XAML, how would I do it?

这不起作用,但正如您所看到的,我正在尝试在 XAML 中设置 stackPanel 的 DataContext,我该怎么做?

Thanks!

谢谢!

回答by Abbas

This brief articleexplains the two ways of setting the DataContext: through XAML or through code. Here's the code:

这篇简短的文章解释了设置 DataContext 的两种方法:通过 XAML 或通过代码。这是代码:

public class HelloWorldDataContextModel
{
    public string HelloWorld { get; set; }

    public HelloWorldDataContextModel()
    {
        HelloWorld = "Hello world!";   
    }
}

And the XAML:

和 XAML:

<Window x:Class="HelloWorldDataContext.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"       
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"        
        xmlns:local="clr-namespace:HelloWorldDataContext"        
        Title="MainWindow" Height="350" Width="525">    

    <Window.Resources>
        <local:HelloWorldDataContextModel x:Key="HelloWorldDataContext" />   
    </Window.Resources>    

    <Grid DataContext="{StaticResource HelloWorldDataContext}">        
        <TextBox HorizontalAlignment="Left" Height="23" Margin="222,127,0,0" TextWrapping="Wrap" Text="{Binding HelloWorld}" VerticalAlignment="Top" Width="120"/>    
    </Grid>
</Window>

回答by Kcvin

To add to Abbas's answer, when you have a parameterless constructor, which you might find happen more often when applying MVVM, you can also set the DataContextof a control a difference way.

添加到 Abbas 的答案中,当您有一个无参数构造函数时,您可能会发现在应用 MVVM 时更频繁地发生这种情况,您还可以DataContext以不同的方式设置控件的 。

<Window x:Class="HelloWorldDataContext.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"       
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"        
        xmlns:local="clr-namespace:HelloWorldDataContext"        
        Title="MainWindow" Height="350" Width="525">    

    <Window.DataContext>
        <local:HelloWorldDataContextModel />   
    </Window.DataContext>    

    <Grid>        
        <TextBox HorizontalAlignment="Left" Height="23" Margin="222,127,0,0" TextWrapping="Wrap" Text="{Binding HelloWorld}" VerticalAlignment="Top" Width="120"/>    
    </Grid>
</Window>

You will get the same result using mine or Abbas's method; however when parameter's are required by a constructor, it's not worth it to go about this way.

使用我的或阿巴斯的方法你会得到同样的结果;然而,当构造函数需要参数时,这样做是不值得的。

回答by yo chauhan

I dont know why you trying to set DataContext of StackPanel though you can set DataContext of Window and use it further, but still if you want to then try this

我不知道你为什么要设置 StackPanel 的 DataContext 虽然你可以设置 Window 的 DataContext 并进一步使用它,但如果你想再试试这个

xaml

xml

 <StackPanel x:Name="stackPanel" DataContext="{Binding Person}">

xaml.cs

xml文件

    public partial class MainWindow : Window, INotifyPropertyChanged
{
    public MainWindow()
    {
        InitializeComponent();
        DataContext = this;
        Person = new Person { FirstName = "Matt", LastName = "Smith" };
    }
    Person person;
    public Person Person
    {
        get { return person; }
        set { person = value; OnPropertyChanged("Person"); }
    }

    public event PropertyChangedEventHandler PropertyChanged;

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

Or instead of Setting DataContext of StackPanel use dataContext of Window and Bind textblock text like Person.FirstName .....

或者,不是设置 StackPanel 的 DataContext,而是使用 Window 的 dataContext 和像 Person.FirstName 那样绑定文本块文本 .....

<TextBox x:Name="textBox_FirstName" Width="200" Margin="0,100,0,0" Text="{Binding Path=Person.FirstName, UpdateSourceTrigger=PropertyChanged}"  />
    <TextBox x:Name="textBox_LastName" Width="200" Margin="0,10,0,0" Text="{Binding Path=Person.LastName, UpdateSourceTrigger=PropertyChanged}" />
    <TextBlock x:Name="textBlock_FullName"  Background="LightBlue" Width="200" Margin="0,10,0,0" Text="{Binding Path=Person.FullName, UpdateSourceTrigger=PropertyChanged}"  />