如果在字段中键入时,如何使Expander标题与ListBox项一起更改?
*我只是试图用图片发布这个,但是这个网站不允许我发布图像,直到我的声誉大于10.该图像只是正在运行的WPF程序的窗口捕获( (点击下面的源代码)点击[New]按钮一次,“John Henry Doe”进入名称字段,“123-4567”进入Phone字段,然后用粗体红色“1)我在这里输入”用箭头指向到名称和电话字段,然后用粗体红色“2)这改变”用箭头指向列表框中的“John Henry Doe:123-4567”项目,然后用粗体红色“3”但这不会改变“指向扩展器标题的“新联系人”的箭头。 *
在上图中可以看到(如果我被允许发布图像),当用户在“名称”或“电话”字段中键入时,列表框项目会发生变化。它会改变,因为我在KeyUp事件上执行.Refresh()。但是,扩展器的标题应该同时改变。据我所知,没有.Refresh()。我希望Expander的Header能够像ListBox的Item一样更新,也就是说,当用户输入时。
ListBox的DataContext是类Contact的可观察集合。 Contact类有一个名为ListString的属性,带有一个get,它返回方法ListItem()的结果。 ListBox的ItemTemplate只是绑定到ListString属性。 Expander的Header绑定到ListBox的SelectedItem.ListString,并且当前仅在选择不同的ListBox项时更新。我需要它在输入时更新。
下面是代码背后的XAML和C#代码。在ListBox中选择一个条目之前,ListBox右侧的控件是不可见的。 [New]按钮将一个新项目插入ListBox并选择它,从而将控件置于右侧以显示并聚焦给Name字段。当您在“名称”字段和/或“电话”字段中键入时,ListBox中的相应项将更新,但不会更新Expander的标题。直到您在ListBox中选择另一个项目时才会更新。我希望它在ListBox项目更新的同时更新。我该怎么做?
<Window x:Class="Binding_List_Expander_04.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Binding List Expander 04"
Height="350"
Width="530">
<Window.Resources>
</Window.Resources>
<Grid>
<StackPanel Orientation="Horizontal" Margin="3">
<StackPanel Orientation="Vertical" Margin="3">
<ListBox Name="ContactList"
ItemsSource="{Binding}"
Width="166"
Height="270"
Margin="0,0,0,3">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=ListString}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Button Name="NewItem"
Content="New"
Click="Event_NewContact_Click"
Height="23"
Width="75" />
</StackPanel>
<StackPanel Orientation="Vertical">
<StackPanel.Resources>
<Style TargetType="ScrollViewer">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=ContactList, Path=SelectedIndex}" Value="-1">
<Setter Property="Opacity" Value="0" />
</DataTrigger>
</Style.Triggers>
</Style>
</StackPanel.Resources>
<ScrollViewer Height="302">
<StackPanel Orientation="Vertical">
<Expander Name="ContactExpander">
<Expander.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding ElementName=ContactList, Path=SelectedItem.ListString}" />
</DataTemplate>
</Expander.HeaderTemplate>
<StackPanel Margin="21,0,0,0"
Orientation="Vertical">
<Grid Margin="3"
TextBoxBase.TextChanged="Event_ContactName_TextChanged">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="3" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="3" />
<ColumnDefinition Width="250" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0"
Grid.Column="0"
Text="Name:" />
<TextBox Grid.Row="0"
Grid.Column="2"
Name="ContactName"
Text="{Binding ElementName=ContactList, Path=SelectedItem.Name, Mode=TwoWay}" />
<TextBlock Grid.Row="2"
Grid.Column="0"
Text="Phone:" />
<TextBox Grid.Row="2"
Grid.Column="2"
Name="ContactPhone"
Text="{Binding ElementName=ContactList, Path=SelectedItem.Phone, Mode=TwoWay}" />
</Grid>
</StackPanel>
</Expander>
<Expander Header=" This is a place holder, there will be many Expanders following this one."
Margin="0,10,0,0">
<StackPanel>
<TextBlock Text="Data and Information" FontSize="30" TextAlignment="Center" />
</StackPanel>
</Expander>
<Expander Header="This is another place holder."
Margin="0,10,0,0">
<StackPanel>
<TextBlock Text="Data and Information" FontSize="30" TextAlignment="Center" />
</StackPanel>
</Expander>
<Expander Header="This is another place holder."
Margin="0,10,0,0">
<StackPanel>
<TextBlock Text="Data and Information" FontSize="30" TextAlignment="Center" />
</StackPanel>
</Expander>
</StackPanel>
</ScrollViewer>
</StackPanel>
</StackPanel>
</Grid>
</Window>
using System.Windows;
using System.Collections.ObjectModel;
using System.Windows.Threading;
using System.Threading;
using System.Windows.Controls;
namespace Binding_List_Expander_04
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
ObservableCollection<Contact> Contacts = new ObservableCollection<Contact>();
public MainWindow()
{
InitializeComponent();
ContactList.DataContext = Contacts;
}
private void Event_NewContact_Click(object sender, RoutedEventArgs e)
{
Contacts.Insert(0, new Contact());
ContactList.SelectedIndex = 0;
if (ContactExpander.IsExpanded)
SetFocus(ContactName);
else
{
ContactExpander.IsExpanded = true;
SetFocus(ContactName);
}
}
public void SetFocus(UIElement control)
{
control.Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, (ThreadStart)delegate { control.Focus(); });
}
private void Event_ContactName_TextChanged(object sender, TextChangedEventArgs e)
{
var tb = e.Source as TextBox;
Contact C = ContactList.SelectedItem as Contact;
if (tb == ContactName)
C.Name = tb.Text;
else if (tb == ContactPhone)
C.Phone = tb.Text;
ContactList.Items.Refresh();
}
}
public class Contact
{
public string Name { get; set; }
public string Phone { get; set; }
public string ListString { get { return ListItem(); } } // See comments in ListItem() below.
public Contact()
{
Name = string.Empty;
Phone = string.Empty;
}
private string ListItem()
{/*
* This is a simplified version, the actual version is complicated and cannot be templatized.
* Please, do not suggest templitazing this. I know this simple version can be templitazed,
* but the actual version cannot be templatized. I need to know how to make this work as it
* currently is.
*/
if ((Name + Phone).Trim().Length == 0)
return "<New Contact>";
else
{
string li = Name.Trim();
if (li.Length != 0 && Phone.Trim().Length != 0) li += ": ";
return li + Phone.Trim();
}
}
}
}
谢谢你的帮助。