两个文本框的数据绑定

时间:2011-10-25 01:40:00

标签: c# wpf

我有2个文本框,每个文本框都在不同的列表视图中。第一个文本框应该显示来自xml文件的数据。因此,当我单击文本框时,第一个文本框中的数据将显示在第二个文本框中。我通过做一个非常大的回合来做到这一点,当我点击它并附加到另一个列表视图时获取特定对象。是否有更短的方法通过xaml中的元素名称绑定来完成此操作? textbox1中的elementName将是textbox2的名称。我尝试这样做,但我不确定我的道路应该是什么?

抱歉不包括我的xaml。

<Window x:Class="GridViewTest.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     xmlns:diag="clr-namespace:System.Diagnostics;assembly=WindowsBase"
    xmlns:local="clr-namespace:GridViewTest"
    Title="MainWindow" mc:Ignorable="d" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" d:DesignHeight="541" d:DesignWidth="858" SizeToContent="WidthAndHeight">
<Window.Resources>
    <local:PacketList x:Key="PacketList"/>
    <local:BindableSelectionTextBox x:Key="BindableSelectionTextBox"/>
</Window.Resources>
<Grid Height="500" Width="798">
    <Grid.RowDefinitions>
        <RowDefinition Height="142*" />
        <RowDefinition Height="145*" />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="234*" />
        <ColumnDefinition Width="233*" />
    </Grid.ColumnDefinitions>
    <ListView ItemsSource="{Binding}" x:Name="lvItems" Grid.RowSpan="2" Grid.ColumnSpan="2">
        <ListView.View>
            <GridView AllowsColumnReorder="True">
                <GridViewColumn Header="Header" Width="200">
                    <GridViewColumn.CellTemplate>
                        <DataTemplate>
                            <Grid>
                                <TextBox Name ="A" Tag="Header" Text="{Binding SelectedText, Path=headerObj.headervalue}" PreviewMouseLeftButtonUp="Handle_Click"
                                         IsReadOnly="True" BorderThickness="0" >
                                </TextBox>
                            </Grid>
                        </DataTemplate>
                    </GridViewColumn.CellTemplate>
                </GridViewColumn>
            </GridView>
        </ListView.View>
    </ListView>
    <ListView Margin="0,245,0,8" Grid.ColumnSpan="2" Grid.RowSpan="2" >
        <TextBox  Name="headText" Text="{Binding SelectedText,ElementName=A}"/>
    </ListView>    
</Grid>

2 个答案:

答案 0 :(得分:1)

首先让我们对WPF中的NameScoping进行一些教育。在WPF中,Templates中的任何绑定仅限于Template。此外,模板中指定的任何元素都不可用于模板外的Binding.ElementName引用。

因此,在您的情况下,TextBox A无法引用TextBox headText,因为文本框A的名称范围是GridViewColumn.CellTemplate

为什么headText下的ListView文本框? ItemsControlsListBoxListViewDataGrid不应用作托管单个元素的面板或容器。他们的目的是展示多个项目。请改用PanelContentControl

   <Grid Margin="0,245,0,8" Grid.ColumnSpan="2" Grid.RowSpan="2" >
       <TextBox  Name="headText" Text="{Binding SelectedText,ElementName=A}"/>
   </Grid>

OR

   <ContentControl Margin="0,245,0,8" Grid.ColumnSpan="2" Grid.RowSpan="2" >
       <TextBox  Name="headText" Text="{Binding SelectedText,ElementName=A}"/>
   </ContentControl>

现在要同步两个文本框之间的选择,请使用以下技巧...

<强> XAML

    <TextBox Name="SelectionSource"
             Tag="{Binding ElementName=SelectionTarget}"
             SelectionChanged="SelectionSource_SelectionChanged" />
    <TextBox Name="SelectionTarget"
             Text="{Binding SelectedText, ElementName=SelectionSource,
                            Mode=TwoWay, UpdateSourceTrigger=Explicit}" />

代码背后......

    private void SelectionSource_SelectionChanged(object sender, RoutedEventArgs e)
    {
        var targetTextBox = ((TextBox) sender).Tag as TextBox;
        if (targetTextBox != null)
        {
            var bndExp
                = BindingOperations.GetBindingExpression(
                    targetTextBox, TextBox.TextProperty);

            if (bndExp != null)
            {
                bndExp.UpdateTarget();
            }
        }
    }

如果您正在使用MVVM,则在附加行为中处理此SelectionSource_SelectionChanged事件。

编辑2:

现在,如果一个文本框是ListBox模板的一部分,而另一个文本框在模板之外,那么使用内容控制hack ......

<强> XAML:

   <Window.Resources>      
    <TextBox x:Key="SelectionTarget"
             Text="{Binding Tag.SelectedText,
                            RelativeSource={RelativeSource Self},
                            Mode=TwoWay,
                            UpdateSourceTrigger=Explicit}" />
  </Window.Resources>

  <StackPanel>
     <ListBox>
        <ListBox.ItemsSource>
            <x:Array Type="{x:Type System:String}">
                <System:String>Test String 1</System:String>
                <System:String>Test String 2</System:String>
                <System:String>Test String 3</System:String>
            </x:Array>
        </ListBox.ItemsSource>
        <ListBox.ItemTemplate>
            <DataTemplate>
                <TextBox Name="SelectionSource"
                         Text="{Binding Path=., Mode=TwoWay}" 
                         Tag="{StaticResource SelectionTarget}"
                         SelectionChanged="SelectionSource_SelectionChanged" />
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>

    <ContentControl Content="{StaticResource SelectionTarget}">           
    </ContentControl>

</StackPanel>

代码背后

    private void SelectionSource_SelectionChanged(
       object sender, RoutedEventArgs e)
    {
        var targetTextBox
             = ((TextBox) sender).Tag as TextBox;
        if (targetTextBox != null)
        {
            targetTextBox.Tag = (TextBox) sender;

            var bndExp
                = BindingOperations.GetBindingExpression(
                    targetTextBox, TextBox.TextProperty);

            if (bndExp != null)
            {
                bndExp.UpdateTarget();
            }
        }
    }

希望这有帮助。

答案 1 :(得分:0)

我不确定您尝试绑定的“SelectedText”是怎么回事,但是如果您要做的就是在“headText”TextBox中显示“lvItems”SelectedItem文本,则以下内容应该有效< / p>

<TextBox Name="headText" Text="{Binding ElementName=lvItems, Path=SelectedItem.headerObj.headervalue}" />

您还需要更改TextBox“A”绑定。

<TextBox Name ="A" Tag="Header" Text="{Binding headerObj.headervalue}" IsReadOnly="True" BorderThickness="0" >
</TextBox>

假设headerObj是Packet类的属性,headervalue是该属性的属性,headervalue是您希望绑定的值。

更改SelectedItem时,“headText”中的文本将更新(而不是在单击TextBox时)。