Hello there,
I'm new to WPF and its Databinding, but I stumbled upon a strange behaviour I could not resolve for myself.
In a Dialog I've got a Listbox with Users and a TextBox for a username. Both are bound to a UserLogonLogic-which publishes among others a CurrentUser
property.
I want the TextBox to update its text when I click on a name in the ListBox. I also want the SelectedItem
in the ListBox to be updated when I enter a username directly into the TextBox. Partial names in the TextBox will be reloved to the first matching value in the listbox or null if there is none.
At first the TextBox gets updated every time I click into the ListBox. Debug shows me that every time the PropertyChangeEvent
for CurrentUser
is fired the method txtName_TextChanged
method is called. Only after I have typed something into the textbox the DataBinding
of the TextBox seems to be lost. There will be no further updates of the TextBox when I click into the ListBox. Debug now shows me that the method txtName_TextChanged
is no longer being called after the CurrentUser
PropertyChangeEvent
is fired.
Does anybody have an idea where I could have gone wrong?
Thanks a lot
Rü
UserLogon.xaml:
<ListBox Grid.Column="0" Grid.Row="1" Grid.RowSpan="4" MinWidth="100" Margin="5" Name="lstUser" MouseUp="lstUser_MouseUp"
ItemsSource="{Binding Path=Users}" SelectedItem="{Binding Path=CurrentUser, Mode=TwoWay}"/>
<TextBox Grid.Column="1" Grid.Row="1" Margin="3" Name="txtName" TextChanged="txtName_TextChanged"
Text="{Binding Path=CurrentUser, Mode=OneWay}" />
UserLogon.xaml.cs:
public UserLogon()
{
InitializeComponent();
_logic = new UserLogonLogic();
TopLevelContainer.DataContext = _logic;
}
private int _internalChange = 0;
private void txtName_TextChanged(object sender, TextChangedEventArgs e)
{
if (_internalChange > 0)
{
return;
}
_internalChange++;
string oldName = txtName.Text;
User user = _logic.SelectByPartialUserName(oldName);
string newName = (user == null) ? "" : user.Name;
if (oldName != newName)
{
txtName.Text = (newName == "") ? oldName : newName;
txtName.Select(oldName.Length, newName.Length);
}
_internalChange--;
}
UserLogon.Logic.cs:
public class UserLogonLogic : INotifyPropertyChanged
{
private User _currentUser;
public User CurrentUser
{
get { return _currentUser; }
set
{
if (value != CurrentUser)
{
_currentUser = value;
OnPropertyChanged("CurrentUser");
}
}
private IEnumerable<User> _users;
public IEnumerable<User> Users
{
get
{
if (_users == null)
{
List<User> _users = Database.GetAllUsers();
}
return _users;
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string prop)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(prop));
}
}
public User SelectByPartialUserName(string value)
{
if (value != "")
{
IEnumerable<User> allUser = GetAllUserByName(value);
if (allUser.Count() > 0)
{
CurrentUser = allUser.First();
}
else
{
CurrentUser = null;
}
}
else
{
CurrentUser = null;
}
return CurrentUser;
}
private IEnumerable<User> GetAllUserByName(string name)
{
return from user in Users
where user.Name.ToLower().StartsWith(name.ToLower())
select user;
}
}