我有一个使用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类属性?
提前致谢
答案 0 :(得分:1)
使用显式绑定 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您可以创建一个viewmodel作为实例,并通过您从代码隐藏中轻松执行viewmodel的方式将其作为datacontext提供。对于这种类型的情况,它节省了一天!
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;
}
我认为通过这种方式你不需要两种方式。 OneWay没问题。因为您明确更改了VM。
注意:我在SO上编码,没有再次测试。希望有帮助!
答案 1 :(得分:1)
我遇到了同样的问题,我在这里找到了:https://stackoverflow.com/a/11676076/4551080
<TextBox Text="{Binding Path=EmailAddress, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
因此请务必设置
UpdateSourceTrigger=PropertyChanged默认值为LostFocus
答案 2 :(得分:0)
使用此解决方法:
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的主要降级但是嘿,在WinFT中有很多更可怕的东西在WPF中缺失:)