在一个Silverlight MVVMLight 4.0应用程序我有一个列表框,文本框和复选框。 列表框的ItemsSource绑定到视图模型对象的列表。 列表框的的SelectedItem是双向绑定到视图模型的对象(SelectedActivity)。

这两个文本框的文本和对应的复选框的IsSelected属性绑定到视图模型的SelectedActivity对象(名称和选定的属性)双向的。 没有代码隐藏。

此工作正常:改变名称在文本框中或检查/取消选中复选框,然后跳格将改变对象的基础属性

但是,当我更改名称(或选中状态),然后immediatelly单击列表中的其他项目,变更未注册。

任何人是否有一种解决方法呢?

样的问候,

卡雷尔

这是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();
        }
    }
}

和将它设置为这样的TextBoxBehaviors是命名空间这里我把上面的类):

 <TextBox Behaviors:TextChangedBindingBehavior.Instance="" Text="{Binding Name, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true}" />

其他提示

我碰到这样的文本框用的问题,但没有看到它的影响复选框。文本框问题发生,因为绑定文本进行了更新,则焦点将丢失。这就是为什么如果你选项卡,然后再更改选择它作为你的期望。如果你改变选择,因为聚焦丢失邮件到达太晚直接绑定文本未更新。

处理这个问题的一种方法是强制绑定更新在文本框中每次用户类型的文本。您可以自定义的行为,以保持它的MVVM。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top