Windows 8 XAML文本更新的数据绑定改变

本文关键字:数据绑定 改变 更新 文本 XAML Windows | 更新日期: 2023-09-27 18:07:42

我有一个使用MVVM模式的windows 8 XAML/c#应用程序。

表单上的所有文本框的文本属性都绑定到我的MVVM类的属性上。

其中一个文本框是这样的:

<TextBox x:Name="textAddressLine1" Text="{Binding AddressLine1, Mode=TwoWay}"/>

MVVM类的属性是这样的:

    private string addressLine1;
    public string AddressLine1
    {
        get { return addressLine1; }
        set
        {
            if (addressLine1 == value)
            {
                return;
            }
            addressLine1 = value;
            RaisePropertyChanged("AddressLine1");
        }
    }

当我输入到我的文本框中,MVVM类没有更新。只有当焦点移动到另一个控件时,它才会更新。

当文本框上的文本发生变化时,我如何更新MVVM类属性?

Thanks in advance

Windows 8 XAML文本更新的数据绑定改变

使用显式绑定textAddressLine1

<TextBox x:Name="textAddressLine1" Text="{Binding AddressLine1,UpdateSourceTrigger=Explicit, Mode=TwoWay}" TextChanged="textAddressLine1_Changed"/>

private void textAddressLine1_Changed(object sender, RoutedEventArgs e)
{  
BindingExpression be = textAddressLine1.GetBindingExpression(TextBox.TextProperty);
be.UpdateTarget();
}

我没有测试代码,但应该可以工作。

编辑:我看到它UpdateSourceTrigger是不存在的环境

您可以创建一个视图模型作为实例,并通过您可以轻松地从代码后执行视图模型的方式将其作为数据上下文。对于这种类型的情况,它节省了一天!

 public MyClassViewModel ViewModel {get;set} 
 ctor()
 {
   this.ViewModel=new MyClassViewModel();
   this.DataContext=this.ViewModel;
   InitializeComponets();
 }
 private void textAddressLine1_Changed(object sender, RoutedEventArgs e)
 {  
   this.ViewModel.AddressLine1=textAddressLine1.Text;
 }
我认为这样你就不需要两条路了。单程就行。因为您显式地更改了VM。

注意:我在SO上编码,没有再次测试。希望会有帮助!

我有同样的问题,我在这里发现:https://stackoverflow.com/a/11676076/4551080

<TextBox Text="{Binding Path=EmailAddress, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />

所以一定要设置

UpdateSourceTrigger=PropertyChanged
默认值是LostFocus

使用以下方法:

public class ExtendedTextBox : TextBox
    {
        public static readonly DependencyProperty CustomActionProperty =
            DependencyProperty.Register(
            "CustomAction",
            typeof(Action<string>),
            typeof(ExtendedTextBox),
            new PropertyMetadata(null, OnPropertyChanged));
        public Action<string> CustomAction 
        {
            get
            {
                return (Action<string>)GetValue(CustomActionProperty);
            }
            set
            {
                SetValue(CustomActionProperty, value);
            }
        }
        private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if(e.NewValue != null)
                (d as ExtendedTextBox).TextChanged += ExtendedTextBox_TextChanged;
            else
                (d as ExtendedTextBox).TextChanged -= ExtendedTextBox_TextChanged;
        }
        async static void ExtendedTextBox_TextChanged(object sender, TextChangedEventArgs e)
        {            
            await CoreWindow.GetForCurrentThread().Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => (sender as ExtendedTextBox).CustomAction((sender as ExtendedTextBox).Text));
        }        
    }

在你的模型中:

public Action<string> UpdateBindedViewModelProperty
        {
            get { return new Action<string>((value) => NewLabelName = value); }
        }

和观点:

<plmrfc:extendedtextbox customaction="{Binding UpdateBindedViewModelProperty, Mode=OneTime}" text="{Binding Path=NewLabelName, Mode=TwoWay}" width="200" x:name="Label_TextBox"></plmrfc:extendedtextbox>

还有另一种方法,它不涉及子类化TextBox。也许你更喜欢这个:

using System.Reflection;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
namespace Flexman
{
    public class TextBoxUpdateSourceBehaviour
    {
        private static PropertyInfo _boundProperty;
        public static readonly DependencyProperty BindingSourceProperty =
            DependencyProperty.RegisterAttached(
            "BindingSource", 
            typeof(string), 
            typeof(TextBoxUpdateSourceBehaviour),
            new PropertyMetadata(default(string), OnBindingChanged));
        public static void SetBindingSource(TextBox element, string value)
        {
            element.SetValue(BindingSourceProperty, value);
        }
        public static string GetBindingSource(TextBox element)
        {
            return (string)element.GetValue(BindingSourceProperty);
        }
        private static void OnBindingChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var txt = d as TextBox;
            if (txt == null)
                return;
            txt.Loaded += OnLoaded;
            txt.TextChanged += OnTextChanged;
        }
        static void OnLoaded(object sender, RoutedEventArgs e)
        {
            var txt = sender as TextBox;
            if (txt == null)
                return;
            // Reflect the datacontext of the textbox to find the field to bind to.
            var dataContextType = txt.DataContext.GetType();
            _boundProperty = dataContextType.GetRuntimeProperty(GetBindingSource(txt));
            // If you want the behaviour to handle your binding as well, uncomment the following.
            //var binding = new Binding();
            //binding.Mode = BindingMode.TwoWay;
            //binding.Path = new PropertyPath(GetBindingSource(txt));
            //binding.Source = txt.DataContext;
            //BindingOperations.SetBinding(txt, TextBox.TextProperty, binding);
        }
        static void OnTextChanged(object sender, TextChangedEventArgs e)
        {
            var txt = sender as TextBox;
            if (txt == null)
                return;
            if (_boundProperty.GetValue(txt.DataContext).Equals(txt.Text)) return;
            _boundProperty.SetValue(txt.DataContext, txt.Text);
        }
    }
}

和视图

<TextBox Text="{Binding Username}" Flexman:TextBoxUpdateSourceBehaviour.BindingSource="Username" />

这是我知道的最漂亮的解决方案。其他将是"非通用"的黑客。祝你好运。我同意这是对silverlight/WPF的重大降级,但是嘿,WinRT中有很多更可怕的东西在WPF中没有:)