Silverlight MVVM - Привязка Twoway не уволена в ListBox Нажмите
-
25-09-2019 - |
Вопрос
В приложении Silverlight MVVMLight 4.0 у меня есть список списка, текстовое поле и флажок. Элементы элементов ListBox связаны с списком объектов в ViewModel. Выполненный элемент ListBox является двусторонним привязкой к объекту (выявленности) в ViewModel.
Оба текста TextBox и свойства Isselected CheckBox являются двусторонним значением, связанным с объектом выставленного актексирования (имя и выбранные свойства) в ViewModel. Нет кодовых
Это работает нормально: изменение имени в текстовом поле или проверку / снятие флажков, а затем в табуке изменят основное свойство объекта.
Но когда я изменяю имя (или проверенное состояние), а затем немедленно щелкните другой элемент в списке, изменение не зарегистрировано.
У кого-нибудь есть обходной путь для этого?
с уважением,
Карел
Это XAML:
<ListBox Height="251" HorizontalAlignment="Left" Margin="11,39,0,0" Name="activitiesListBox" ItemsSource="{Binding Activities.Items}" VerticalAlignment="Top" Width="139"
SelectedItem="{Binding Activities.SelectedActivity, Mode=TwoWay}">
Это класс деятельности, удерживающий элементы, связанные с списком:
public class CLJActivitiesViewModel : ViewModelBase
{
/// <summary>
/// Initializes a new instance of the ActivitiesViewModel class.
/// </summary>
public CLJActivitiesViewModel()
{
////if (IsInDesignMode)
////{
//// // Code runs in Blend --> create design time data.
////}
////else
////{
//// // Code runs "for real": Connect to service, etc...
////}
}
#region items
/// <summary>
/// The <see cref="Items" /> property's name.
/// </summary>
public const string ItemsPropertyName = "Items";
private ObservableCollection<CLJActivityViewModel> m_Items = null;
/// <summary>
/// Gets the Items property.
/// TODO Update documentation:
/// Changes to that property's value raise the PropertyChanged event.
/// This property's value is broadcasted by the Messenger's default instance when it changes.
/// </summary>
public ObservableCollection<CLJActivityViewModel> Items
{
get
{
return m_Items;
}
set
{
if (m_Items == value)
{
return;
}
var oldValue = m_Items;
m_Items = value;
RaisePropertyChanged(ItemsPropertyName, oldValue, value, true);
}
}
#endregion
#region SelectedActivity
/// <summary>
/// The <see cref="SelectedActivity" /> property's name.
/// </summary>
public const string SelectedActivityPropertyName = "SelectedActivity";
private CLJActivityViewModel m_SelectedActivity = null;
/// <summary>
/// Gets the SelectedActivity property.
/// TODO Update documentation:
/// Changes to that property's value raise the PropertyChanged event.
/// This property's value is broadcasted by the Messenger's default instance when it changes.
/// </summary>
public CLJActivityViewModel SelectedActivity
{
get
{
return m_SelectedActivity;
}
set
{
if (m_SelectedActivity == value)
{
return;
}
var oldValue = m_SelectedActivity;
m_SelectedActivity = value;
RaisePropertyChanged(SelectedActivityPropertyName, oldValue, value, true);
}
}
#endregion
public override void Cleanup()
{
// Clean own resources if needed
base.Cleanup();
}
}
Решение
Я столкнулся с тем же вопросом. Я должен был вызвать обновление, так как пользователь вводил текст, чтобы я мог сделать некоторую проверку.
Простой способ добиться этого состоит в том, чтобы создать пользовательское поведение, которое вы можете добавить в любой TextBox
.
Шахта выглядит следующим образом:
public static class TextChangedBindingBehavior
{
public static readonly DependencyProperty InstanceProperty =
DependencyProperty.RegisterAttached("Instance", typeof(object), typeof(TextChangedBindingBehavior), new PropertyMetadata(OnSetInstanceCallback));
public static object GetInstance(DependencyObject obj)
{
return (object)obj.GetValue(InstanceProperty);
}
public static void SetInstance(DependencyObject obj, object value)
{
obj.SetValue(InstanceProperty, value);
}
private static void OnSetInstanceCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var textBox = d as TextBox;
if (textBox != null)
{
textBox.TextChanged -= OnTextChanged;
textBox.TextChanged += OnTextChanged;
}
}
private static void OnTextChanged(object sender, TextChangedEventArgs e)
{
var textBox = (TextBox)sender;
if(!DesignerProperties.GetIsInDesignMode(textBox))
{
textBox.GetBindingExpression(TextBox.TextProperty).UpdateSource();
}
}
}
и вы установили его на TextBox
как это (Behaviors
это пространство имен, где я положил класс выше):
<TextBox Behaviors:TextChangedBindingBehavior.Instance="" Text="{Binding Name, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true}" />
Другие советы
Я бежал в эту проблему с TextBox, но не видел, что он влияет на флажок. Проблема TextBox происходит, потому что связанный текст обновляется, то фокус потерян. Вот почему, если вы сначала вкладка, а затем измените свой выбор, он работает, как вы ожидаете. Если вы измените выбор, напрямую связанный текст не обновляется с тех пор, как утерянное сообщение Focus поступает слишком поздно.
Один из способов решения этой проблемы состоит в том, чтобы заставить обновление связывания каждый раз, когда пользовательские типы пользователей текст в текстовом поле. Вы можете сделать пользовательское поведение, чтобы сохранить его MVVM.