Я новичок в WPF и его привязке к данным, но наткнулся на странное поведение, которое не смогу разрешить для себя.
В диалоге у меня есть список с пользователями и текстовое поле для имени пользователя. Оба связаны с UserLogonLogic, который публикует среди прочего свойство CurrentUser
.
Я хочу, чтобы TextBox обновлял свой текст, когда я нажимаю на имя в ListBox. Я также хочу, чтобы SelectedItem
в ListBox обновлялся, когда я вводил имя пользователя прямо в TextBox. Частичные имена в TextBox будут преобразованы в первое совпадающее значение в списке или пустое значение, если их нет.
Сначала TextBox обновляется каждый раз, когда я нажимаю на ListBox. Отладка показывает мне, что каждый раз при запуске PropertyChangeEvent
для CurrentUser
вызывается метод txtName_TextChanged
. Только после того, как я что-то ввел в текстовое поле, DataBinding
TextBox, похоже, теряется. Больше не будет никаких обновлений TextBox, когда я нажму на ListBox. Отладка теперь показывает мне, что метод txtName_TextChanged
больше не вызывается после запуска CurrentUser
PropertyChangeEvent
.
У кого-нибудь есть идеи, где я мог ошибиться?
Большое спасибо
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;
}
}