저는 WPF와 Databinding을 처음 접했지만 스스로 해결할 수없는 이상한 행동을 발견했습니다.WPF lost Databinding
대화 상자에는 사용자가있는 ListBox와 사용자 이름이있는 TextBox가 있습니다. 둘 다 UserLogonLogic에 바인딩되어 있습니다.이 UserLogonLogic은 CurrentUser
속성을 게시합니다.
ListBox에서 이름을 클릭하면 텍스트 상자의 텍스트가 업데이트되기를 원합니다. 또한 TextBox에 사용자 이름을 직접 입력 할 때 ListBox의 SelectedItem
을 업데이트하려고합니다. TextBox의 부분 이름은 목록 상자에서 첫 번째로 일치하는 값으로 확인되거나없는 경우 null로 확인됩니다.
처음에는 ListBox를 클릭 할 때마다 TextBox가 업데이트됩니다. 디버그는 CurrentUser
에 대한 PropertyChangeEvent
이 실행될 때마다 txtName_TextChanged
메서드가 호출된다는 것을 보여줍니다. 텍스트 상자에 뭔가를 입력 한 후에야 TextBox DataBinding
이 손실 된 것 같습니다. ListBox를 클릭하면 TextBox를 더 이상 업데이트하지 않습니다. 디버그 이제 PropertyChangeEvent
이 해고 된 후에 txtName_TextChanged
메서드가 더 이상 호출되지 않음을 보여줍니다.
누구나 내가 잘못했을 수있는 생각이 있습니까?
덕분에 많은
RU
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;
}
}
사실 나는 적극적으로의 TextChanged의 ATTRIB를 설정하기 때문에, 그것은해야한다고 생각하지 말아. 그래서 나는 항상 바인딩을 사용하여 CurrentUser가 변경 될 때 항상 "수동적으로"값을 읽도록 보장합니다. TextBox의 모든 활성 변경 사항은 txtName_TextChanged에 의해 처리됩니다. – Savinien
TwoWay로 시도해 보았습니다. 결과는 프로그램이 제대로 작동하지 않는다는 것입니다. 처음부터 SelectedItem을 사용한 변경 사항은 TextBox에 반영되지 않습니다. – Savinien