问题描述
这是针对 Windows 10 通用应用程序.
This is for a Windows 10 Universal App.
XAML:
<RelativePanel Padding="4" Margin="4,12,0,0">
<TextBlock x:Name="Label" Text="Class Name" Margin="12,0,0,4"/>
<ListView x:Name="ClassTextBoxes"
ItemsSource="{Binding TextBoxList}"
SelectionMode="None" RelativePanel.Below="Label">
<ListView.ItemTemplate>
<DataTemplate >
<RelativePanel>
<TextBox x:Name="tbox"
PlaceholderText="{Binding PlaceHolder}"
Text="{Binding BoxText,
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}"
Padding="4" Width="200" MaxLength="25"/>
<TextBlock x:Name="errorLabel"
RelativePanel.Below="tbox"
Text="{Binding Error, Mode=TwoWay}"
Padding="0,0,0,4"
FontSize="10"
Foreground="Red"/>
<Button Content="Delete" Margin="12,0,0,0" RelativePanel.RightOf="tbox"/>
</RelativePanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</RelativePanel>
型号:
public class TextBoxStrings : BaseModel
{
private string _placeholder;
public string PlaceHolder
{
get { return _placeholder; }
set
{
if (_placeholder != value)
{
_placeholder = value;
NotifyPropertyChanged();
}
}
}
private string _boxText;
public string BoxText
{
get { return _boxText; }
set
{
if (_boxText != value)
{
_boxText = CheckBoxText(value);
NotifyPropertyChanged();
}
}
}
public string CheckBoxText(string val)
{
var r = new Regex("[^a-zA-Z0-9]+");
return r.Replace(val, "");
}
}
视图模型:
private TrulyObservableCollection<TextBoxStrings> _textBoxList;
public TrulyObservableCollection<TextBoxStrings> TextBoxList
{
get { return _textBoxList; }
set
{
if (_textBoxList != value)
{
_textBoxList = value;
RaisePropertyChanged();
}
}
}
然后我从我的视图模型中将新的 TextBoxString
对象添加到我的 TextBoxList
集合中.
and I add new TextBoxString
objects to my TextBoxList
collection from within my view-model.
我想让用户不能输入某些字符(或者更确切地说,他们在每次输入时都会被删除)输入.
这在模型中有效.设置断点并查看值,模型中的一切都在工作:值进入 setter 并被更改,_boxText
保存从 CheckBoxText();
This works...in the model. Setting breakpoints and looking at the values, everything in the Model is working: value goes into the setter and gets changed, _boxText
holds the new value that is set from CheckBoxText();
但问题是,在我的视图中,文本框没有反映我在模型中所做的基础文本的更改.
因此,如果我在tbox"中输入abc*()",模型中的值将是abc".但是,文本框的值仍然是abc*()".
So if I type in "abc*()" into "tbox", the value in the model will be "abc". The value of the textbox, however, will still be "abc*()".
我有一种感觉,这与我正在编辑集合内的项目有关,而我没有实现任何东西来处理集合内的更改项目.我的印象是使用 INotifyPropertyChanged
和 ObservableCollection
会为我解决这个问题.
I have a feeling it has something to do with the fact that I'm editing items that are inside of a collection and I don't have anything implemented to handle changing items within a collection. I was under the impression that using INotifyPropertyChanged
and ObservableCollection<T>
would take care of that for me.
大家有什么建议吗?
谢谢!
所以,现在我尝试使用 TrulyObservableCollection
因为我认为这是问题所在,但它没有帮助.这是:https://gist.github.com/itajaja/7507120
So, now I'm trying to use TrulyObservableCollection
because I thought this was the problem, but it hasn't helped. Here it is: https://gist.github.com/itajaja/7507120
推荐答案
如您所见,TextBox 确实反映了对模型的更改.当您在文本框中输入abc*()"时,模型中的值将更改为abc".这里的问题是 UWP 中的绑定系统是智能的".对于TwoWay 绑定,对目标 的更改将自动传播到源,在这种情况下,绑定系统假定 PropertyChanged 事件将触发源中的相应属性,它会忽略这些事件.因此,即使您的源代码中有 RaisePropertyChanged
或 NotifyPropertyChanged
,TextBox 仍然不会更新.
As you've seen, the TextBox do reflect changes to your model. When you type in "abc*()" in the TextBox, the value in the model will be changed to "abc". The problem here is that the binding system in UWP is "intelligent". For TwoWay bindings, changes to the target will automatically propagate to the source and in this scenario, binding system assumes that the PropertyChanged event will fire for corresponding property in source and it ignores these events. So even you have RaisePropertyChanged
or NotifyPropertyChanged
in you source, the TextBox still won't update.
在 WPF 中,我们可以调用 BindingExpression.UpdateTarget Method 来强制更新.但是这个方法在UWP中不可用.
In WPF, we can call BindingExpression.UpdateTarget Method to force the update. But this method is not available in UWP.
作为一种解决方法,您应该能够使用 TextBox.TextChanged 事件检查输入如下:
As a workaround, you should be able to use TextBox.TextChanged event to check the input like following:
private void tbox_TextChanged(object sender, TextChangedEventArgs e)
{
var tb = sender as TextBox;
if (tb != null)
{
var originalText = tb.Text;
var r = new Regex("[^a-zA-Z0-9]+");
if (originalText != r.Replace(originalText, ""))
{
var index = (tb.SelectionStart - 1) < 0 ? 0 : (tb.SelectionStart - 1);
tb.Text = r.Replace(originalText, "");
tb.SelectionStart = index;
}
}
}
但是它可能会破坏您的 MVVM 模型,您可以使用数据验证来避免这种情况,这里是一个博客:让我们编码吧!在您的 Windows 应用商店应用 (WinRT-XAML) 中处理验证,您可以参考.就我个人而言,数据验证是这种情况下更好的方向.
However it may break your MVVM model, you can use data validation to avoid this and here is a blog: Let’s Code! Handling validation in your Windows Store app (WinRT-XAML) you can refer to. And for my personal opinion, data validation is a better direction for this scenario.
这篇关于双向绑定:在模型设置器中编辑来自 XAML 控件的传递值不会更新控件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!