フィールドへの入力時に ListBox 項目とともに Expander ヘッダーを変更するにはどうすればよいですか?
* これを画像とともに投稿しようとしましたが、このサイトでは、評判が 10 を超えるまで画像を投稿することはできません。画像は、実行中の WPF プログラム (以下のソース) の単なるウィンドウ キャプチャであり、[ [新規] ボタンが 1 回クリックされ、[名前] フィールドに「John Henry Doe」と入力され、[電話] フィールドに「123-4567」と入力された後、赤い太字で [1) ここに入力すると、名前と電話フィールドを指す矢印が表示されます。 、次に ListBox の「John Henry Doe: 123-4567」項目を指す矢印で太字の赤の「2) これは変更されます」、次に太字の赤で「3) しかし、これは変更されません」と「新規」を指す矢印エキスパンダーのヘッダーの「連絡先」。*
(画像の投稿が許可されている場合) 上記の画像に見られるように、ユーザーが名前または電話フィールドに入力すると、ListBox 項目が変更されます。KeyUp イベントで .Refresh() を実行するため、変更されます。ただし、エキスパンダーのヘッダーは同時に変更される必要があります。私の知る限り、そのための . Refresh() はありません。リストボックスのアイテムと同じように、つまりユーザーが入力しているときに、エキスパンダーのヘッダーを更新したい。
ListBox の DataContext は、クラス Contact の監視可能なコレクションです。Contact クラスには、メソッド ListItem() の結果を返す get を持つ ListString というプロパティがあります。ListBox の ItemTemplate は、単純に ListString プロパティにバインドします。Expander の Header は ListBox の SelectedItem.ListString にバインドされており、現在、異なる ListBox アイテムを選択した場合にのみ更新されます。入力が発生すると更新する必要があります。
以下は、XAML および C# コード ビハインド コードです。ListBox の右側にあるコントロールは、ListBox でエントリが選択されるまで表示されません。[New] ボタンは、新しい項目を ListBox に挿入して選択します。これにより、コントロールが右側に表示され、Name フィールドにフォーカスが置かれます。Name フィールドや Phone フィールドに入力すると、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();
}
}
}
}
助けてくれてありがとう。