Reputation: 12293
I'm doing a list of contacts for a person.
I have an ItemsControl
which uses DataTemplates
for different types of contact information. E.g. Phone number, Email... etc
In case of phone number, I want user to have 4 TextBoxes where he can edit the number. 4 because of the format (he can edit numbers only, the format is generated automatically):
+43 (2) 112233 - 2
each part as a TextBox. AND I want to have a main TextBox with the whole number written in that format. That means when a user edits one of those 4 Textboxes, the main TextBox is in real time filled with a formatted number.
I got it working in code behind, but as I'm using DataTemplates now, I want to reach this functionality in XAML. Any Idea how to add triggers to all those 4 TextBoxes in way the main TextBox is regenerated with a correct format?
Upvotes: 1
Views: 3692
Reputation: 178810
You should be able to bind each TextBox
to the same underlying property, and use a converter with the intelligence to extract out the part of the phone number relevant to that TextBox
. Pseudo-code:
<TextBox Text="{Binding PhoneNumber, Converter={StaticResource PhoneNumberConverter, ConverterParameter=CountryCode}}"/>
<TextBox Text="{Binding PhoneNumber, Converter={StaticResource PhoneNumberConverter, ConverterParameter=AreaCode}}"/>
...
If you're doing MVVM, use separate properties in a PhoneNumberViewModel
rather than using a converter.
Upvotes: 1
Reputation: 13025
If I got this correctly and you don't necessarily need to edit the phone number in the main TextBox, you can use multibinding to accomplish this. Here is an example:
<DataTemplate x:Key="PhoneNumberTemplate">
<StackPanel Orientation="Horizontal">
<TextBox Name="tbPN1" />
<TextBox Name="tbPN2" />
<TextBox Name="tbPN3" />
<TextBox Name="tbPN4" />
<TextBox IsReadOnly="True">
<TextBox.Text>
<MultiBinding StringFormat="{}+{0} ({1}) {2} - {3}">
<Binding Path="Text" ElementName="tbPN1" UpdateSourceTrigger="PropertyChanged" />
<Binding Path="Text" ElementName="tbPN2" UpdateSourceTrigger="PropertyChanged" />
<Binding Path="Text" ElementName="tbPN3" UpdateSourceTrigger="PropertyChanged" />
<Binding Path="Text" ElementName="tbPN4" UpdateSourceTrigger="PropertyChanged" />
</MultiBinding>
</TextBox.Text>
</TextBox>
</StackPanel>
</DataTemplate>
This will update the main TextBox every time a key is pressed inside one of the other 4 TextBoxes
Update:
In order to 'update' the data source, I would do the following:
Have the PhoneNumber class implement INotifyPropertyChanged like this:
public class PhoneNumber : INotifyPropertyChanged {
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName) {
var handler = PropertyChanged;
if (handler != null) {
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
private string m_CountryCode;
public string CountryCode {
get { return m_CountryCode; }
set {
m_CountryCode = value;
ComputeFullNumber();
OnPropertyChanged("CountryCode");
}
}
private string m_AreaCode;
public string AreaCode {
get { return m_AreaCode; }
set {
m_AreaCode = value;
ComputeFullNumber();
OnPropertyChanged("AreaCode");
}
}
private string m_Number;
public string Number {
get { return m_Number; }
set {
m_Number = value;
ComputeFullNumber();
OnPropertyChanged("Number");
}
}
private string m_Suffix;
public string Suffix {
get { return m_Suffix; }
set {
m_Suffix = value;
ComputeFullNumber();
OnPropertyChanged("Suffix");
}
}
public string FullNumber { get; private set; }
private void ComputeFullNumber() {
FullNumber = string.Format("+{0} ({1}) {2} - {3}", m_CountryCode, m_AreaCode, m_Number, m_Suffix);
OnPropertyChanged("FullNumber");
}
}
Then your DataTemplate becomes:
<DataTemplate x:Key="PhoneNumberTemplate">
<StackPanel Orientation="Horizontal">
<TextBox Text="{Binding Path=CountryCode, UpdateSourceTrigger=PropertyChanged}" />
<TextBox Text="{Binding Path=AreaCode, UpdateSourceTrigger=PropertyChanged}" />
<TextBox Text="{Binding Path=Number, UpdateSourceTrigger=PropertyChanged}" />
<TextBox Text="{Binding Path=Suffix, UpdateSourceTrigger=PropertyChanged}" />
<TextBox Text="{Binding Path=FullNumber, Mode=OneWay}" IsReadOnly="True" />
</StackPanel>
</DataTemplate>
Upvotes: 2