页首Html代码

WPF 笔记 三 绑定

绑定

HelloWorld

    <StackPanel Margin="10">
        <TextBox Name="txtValue" />
        <WrapPanel Margin="0,10">
            <TextBlock Text="Value: " FontWeight="Bold" />
            <TextBlock Text="{Binding Path=Text, ElementName=txtValue}" />
        </WrapPanel>
    </StackPanel>

 Binding 语法

{Binding Path=NameOfProperty}

简略为

{Binding NameOfProperty}

连接其他UI元素的语法

{Binding Path=Text, ElementName=txtValue}

。。

 DataContext

    <StackPanel Margin="15">
        <WrapPanel>
            <TextBlock Text="Window title:  " />
            <TextBox Text="{Binding Title}" Width="150" />
        </WrapPanel>
        <WrapPanel Margin="0,10,0,0">
            <TextBlock Text="Window dimensions: " />
            <TextBox Text="{Binding Width}" Width="50" />
            <TextBlock Text=" x " />
            <TextBox Text="{Binding Height}" Width="50" />
        </WrapPanel>
    </StackPanel>

在cs文件中

InitializeComponent();
            this.DataContext = this;

xaml绑定的property都是Window对象自身比如title,宽,高。

 

 Window本身的这些属性改变时,值会立即反映到UI显示上。

如果UI上的值改变,需要焦点移动到其他UI控件,Window的那些宽高才会改变。此时UpdateSourceTrigger的值为LostFocus

如果需要Window的那些宽高立即生效的话,binding后面加上UpdateSourceTrigger=PropertyChanged

            <TextBox Text="{Binding Width,UpdateSourceTrigger=PropertyChanged}" Width="50" />

 

UpdateSourceTrigger的值一共有

1.Explicit

2.LostFocus

3.PropertyChanged

 

对于Explicit,这基本上意味着除非您手动执行,否则不会更新源。

explicit手动更新的例子:

            <TextBox Name="txtWindowTitle" Text="{Binding Title, UpdateSourceTrigger=Explicit}" Width="150" />

后台代码

            BindingExpression binding = txtWindowTitle.GetBindingExpression(TextBox.TextProperty);
            binding.UpdateSource();

 

后台代码实现HelloWorld例子中的绑定

    <StackPanel Margin="10">
        <TextBox Name="txtValue" />
        <WrapPanel Margin="0,10">
            <TextBlock Text="Value: " FontWeight="Bold" />
            <TextBlock Name="lblValue" />
        </WrapPanel>
    </StackPanel>
            InitializeComponent();
            Binding binding = new Binding("Text");
            binding.Source = txtValue;
            lblValue.SetBinding(TextBlock.TextProperty, binding);

 响应数据变化

    <DockPanel Margin="10">
        <StackPanel DockPanel.Dock="Right" Margin="10,0,0,0">
            <Button Name="btnAddUser" Click="btnAddUser_Click">Add user</Button>
            <Button Name="btnChangeUser" Click="btnChangeUser_Click" Margin="0,5">Change user</Button>
            <Button Name="btnDeleteUser" Click="btnDeleteUser_Click">Delete user</Button>
        </StackPanel>
        <ListBox Name="lbUsers" DisplayMemberPath="Name"></ListBox>
    </DockPanel>

后台

    public partial class MainWindow : Window
    {
        private ObservableCollection<User> users = new ObservableCollection<User>();
        public MainWindow()
        {
            
            InitializeComponent();
            users.Add(new User() { Name = "John Doe" });
            users.Add(new User() { Name = "Jane Doe" });

            lbUsers.ItemsSource = users;
        }
        private void btnAddUser_Click(object sender, RoutedEventArgs e)
        {
            users.Add(new User() { Name = "New user" });
        }

        private void btnChangeUser_Click(object sender, RoutedEventArgs e)
        {
            if (lbUsers.SelectedItem != null)
                (lbUsers.SelectedItem as User).Name = "Random Name";
        }

        private void btnDeleteUser_Click(object sender, RoutedEventArgs e)
        {
            if (lbUsers.SelectedItem != null)
                users.Remove(lbUsers.SelectedItem as User);
        }

    }

    public class User : INotifyPropertyChanged
    {
        private string name;
        public string Name
        {
            get { return this.name; }
            set
            {
                if (this.name != value)
                {
                    this.name = value;
                    this.NotifyPropertyChanged("Name");
                }
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        public void NotifyPropertyChanged(string propName)
        {
            if (this.PropertyChanged != null)
                this.PropertyChanged(this, new PropertyChangedEventArgs(propName));
        }
    }

 

 RelativeSource例子说明

<StackPanel Margin="10,50,0,0" Orientation="Vertical" ToolTip="top" >

                <StackPanel Orientation="Horizontal" >
                    <TextBlock Width="150" Text="获取自身宽度:"  ></TextBlock>
                    <TextBlock Width="200" Text="{Binding Path=Width,RelativeSource={RelativeSource Mode=Self}}" ></TextBlock>
                </StackPanel>


                <StackPanel Orientation="Horizontal" ToolTip="parent" >
                    <TextBlock Width="150" Text="查找上一层ToolTip:" ></TextBlock>
                    <TextBlock Text="{Binding Path=ToolTip,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type StackPanel}}}"></TextBlock>
                </StackPanel>


                <StackPanel Orientation="Horizontal">
                    <TextBlock Width="150" Text="查找上二层ToolTip:" ></TextBlock>
                    <TextBlock Text="{Binding Path=ToolTip,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type StackPanel},AncestorLevel=2}}"></TextBlock>
                </StackPanel>

            </StackPanel>
可以根据当前目标对象的相对关系指向源目标。比如获取当前对象的父亲对象、兄弟对象或者自身的其他属性等一些数据。
运行显示

 

创建RelativeSource的时候,mode模式有四种类型:

 
 Mode成员名称说明
  FindAncestor

引用数据绑定元素的父链中的上级。 这可用于绑定到特定类型的上级或其子类。 若要指定 AncestorType 和/或 AncestorLevel,这就是应使用的模式。

  PreviousData

允许在当前显示的数据项列表中绑定上一个数据项(不是包含数据项的控件)。

  Self

引用正在其上设置绑定的元素,并允许你将该元素的一个属性绑定到同一元素的其他属性上。

  TemplatedParent

引用应用了模板的元素,其中此模板中存在数据绑定元素。 这类似于设置 TemplateBindingExtension,且仅在 Binding 位于模板内部时适用。

 

Binding Source RelativeSource

Source

Source属性通常用于绑定设置的对象时,是已知的

 <Window x:Name="MainWindow">
         <Grid>
               <Button Background=”{Binding Source={StaticResource ButtonStyle}}”/>
         </Grid>
</Window>

RelativeSource

由于不能确定Source的对象叫什么名字,但知道它与作为Binding目标的对象在UI布局上有相对关系,比如控件自己关联自己的某个数据、关联自己某级容器的数据,就要使用Binding的RelativeSource属性。

     RelativeSource 的三种典型用法:

 /1.UI元素的一个属性绑定在自身的另一个属性上

<Label Background = {Binding Path=Forgroud, RelativeSource={RelativeSource Self}} />

     /2.UI元素的一个属性绑定在某个父元素的属性上

<Grid>
   <Label Background = {Binding Path=Background, RelativeSource={RelativeSource AncestorType={x:Type Grid}}}/>
</Grid>

     /3.Template中的元素的属性绑定在Template使用者元素的属性上

  {Binding Path=PathToProperty, RelativeSource={RelativeSource TemplatedParent}}

如果要绑定到对象上的另一个属性:

{Binding Path=PathToProperty, RelativeSource={RelativeSource Self}}

如果您想获得祖先的属性:

{Binding Path=PathToProperty,
    RelativeSource={RelativeSource AncestorType={x:Type typeOfAncestor}}}

如果希望获得模板父级上的属性(因此可以在ControlTemplate中执行双向绑定)

{Binding Path=PathToProperty, RelativeSource={RelativeSource TemplatedParent}}

或者,更短的(这只适用于OneWay绑定):

{TemplateBinding Path=PathToProperty}

    

例子1:

     <StackPanel DataContext="abc">
        <Label Content="{Binding}"></Label>
        <Label Content="{Binding RelativeSource={RelativeSource Self},Path=DataContext}"></Label>
    </StackPanel>

 

 

例子2:

    <StackPanel DataContext="abc">
        <Label Content="{Binding}"></Label>
        <Label DataContext="def" Content="{Binding RelativeSource={RelativeSource Self},Path=DataContext}"></Label>
    </StackPanel>

 

Binding 为空等效于

{Binding RelativeSource={RelativeSource Self},Path=DataContext}

 从本控件类为开始根据可视树的层次结构自下而上查找不为空的Datacontext属性的值。

 

posted @ 2022-02-05 18:28  noigel  阅读(135)  评论(0编辑  收藏  举报
js脚本