Silverlight MVVM 绑定(bind)更新以不希望的顺序触发

标签 silverlight data-binding silverlight-4.0 mvvm

场景 :在 Silverlight 4 MVVM 项目中,我们有一个 ListBox控件包含项目,所选项目是双向绑定(bind)到 ViewModel 中的相应属性。另一个控件(例如原因,我已将其简化为单个 TextBox )是绑定(bind)到所选项目内容的数据。该值应在离开/失去焦点时更新。

问题 :当TextBox中的值已更改,我们将其保留为 TextBox通过按 Tab 键,一切都按预期工作 - 值被更新。但是,如果用户点击 ListBox 中的不同项目, ,然后在 TextBox 的内容之前触发 SelectedItem setter setter 被触发,没有机会处理用户输入。

Screen

您可以在调试器中看到,当向属性 setter 添加断点时,新的 ListView首先应用选择,在 TextBox 之前更新被处理。

期望的行为 :我们需要知道当前选中的item在用户选择另一个item之前被修改过。不希望有一个自定义更新触发器,它会在每次按键时通知(我们知道这是可能的)。

你能帮我吗?

代码(一个非常简单的例子):

查看型号

public abstract class ViewModelBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(string propertyName)
    {
        var handler = PropertyChanged;
        if (handler != null)
            handler(this, new PropertyChangedEventArgs(propertyName));
    }
}

public class ItemViewModel : ViewModelBase
{
    private string _content;

    public ItemViewModel(string initContent)
    {
        _content = initContent;
    }

    public string Content
    {
        get
        {
            return _content;
        }
        set
        {
            if (_content != value)
            {
                _content = value;
                OnPropertyChanged("Content");
            }
        }
    }
}

public class MainViewModel : ViewModelBase
{
    private ObservableCollection<ItemViewModel> _items =
        new ObservableCollection<ItemViewModel>();
    private ItemViewModel _selectedViewModel;

    public ObservableCollection<ItemViewModel> Items
    {
        get
        {
            return _items;
        }
    }

    public ItemViewModel SelectedItem
    {
        get
        {
            return _selectedViewModel;
        }
        set
        {
            if (_selectedViewModel != value)
            {
                _selectedViewModel = value;
                OnPropertyChanged("SelectedItem");
            }
        }
    }
}

XAML
<Grid x:Name="LayoutRoot" Background="White">
    <ListBox Height="100"
             HorizontalAlignment="Left"
             Margin="12,12,0,0"
             VerticalAlignment="Top"
             ItemsSource="{Binding Items}"
             SelectedItem="{Binding SelectedItem, Mode=TwoWay}"
             DisplayMemberPath="Content"
             Width="220" />
    <TextBox Height="23"
             HorizontalAlignment="Left"
             Margin="12,118,0,0"
             Text="{Binding SelectedItem.Content, Mode=TwoWay}"
             VerticalAlignment="Top"
             Width="220" />
</Grid>

后面的 XAML 代码
    public MvvmTestView()
    {
        InitializeComponent();

        Loaded += new RoutedEventHandler(MvvmTestView_Loaded);
    }

    void MvvmTestView_Loaded(object sender, RoutedEventArgs e)
    {
        MainViewModel viewModel = new MainViewModel();
        viewModel.Items.Add(new ItemViewModel("Hello StackOverflow"));
        viewModel.Items.Add(new ItemViewModel("Thanks to Community"));

        DataContext = viewModel;
    }

更新 1
我提出 a self designed solution供您检查,这可能是被接受的,我仍然想鼓励您发表评论并给出提示。谢谢。

最佳答案

每次在文本框中更改文本时,您可以向文本框添加一个行为以更新绑定(bind)。也许这解决了你的问题。

这是 Behavior 类的代码:

    public class UpdateTextBindingOnPropertyChanged : Behavior<TextBox> {
    // Fields
    private BindingExpression expression;

    // Methods
    protected override void OnAttached() {
        base.OnAttached();
        this.expression = base.AssociatedObject.GetBindingExpression(TextBox.TextProperty);
        base.AssociatedObject.TextChanged+= OnTextChanged;
    }

    protected override void OnDetaching() {
        base.OnDetaching();
        base.AssociatedObject.TextChanged-= OnTextChanged;
        this.expression = null;
    }

    private void OnTextChanged(object sender, EventArgs args) {
        this.expression.UpdateSource();
    }
}

这是 XAML:
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" 
xmlns:local="Namespace of the class where UpdateTextBindingOnPropertyChanged is defined"

<TextBox Text="{Binding SelectedItem.Content, Mode=TwoWay}">
  <i:Interaction.Behaviors>
    <local:UpdateTextBindingOnPropertyChanged />
  </i:Interaction.Behaviors>
</TextBox >

关于Silverlight MVVM 绑定(bind)更新以不希望的顺序触发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5338546/

相关文章:

javascript - 在 mustache Polymer 2.0 中绑定(bind)对象

c# - 将 ComboBox 的 SelectedValue 绑定(bind)到 WPF 中的枚举

c# - 为什么 Winforms.Button.Text 适用于 DataBinding 而不适用于 ImageKey?

silverlight - MEF 和银光 : How do I navigate to a page in another XAP?

silverlight - Silverlight 程序集与 "normal".NET 程序集二进制不兼容的原因

降级为 html 的 Silverlight

javascript - 为什么 WP7 WebBrowser InvokeScript 调用会抛出错误 : 80020101?

c# - 无法将简单的组合框与 mvvm 和 wcf ria 服务绑定(bind)

silverlight - Xaml 找不到绑定(bind)

silverlight - 如何让 Silverlight 数据绑定(bind)在用户键入时更新模型?