我的文本块未更新更新我的模型中的值。如果我更新ViewModel中的文本块它可以工作,所以我的绑定似乎是正确的。我相信问题是我在模型中更新它的方式,但我不确定为什么我的observableCollection只更新,因为我来回传递值不确定这是不错的MVVM策略。
XAML部分:
<Grid>
<TextBox x:Name="NewLabelBx" HorizontalAlignment="Left" Height="23" Margin="54,449,0,0" TextWrapping="Wrap" Text="{Binding NewLabel,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Top" Width="314"/>
<Button x:Name="NewLabelBtn" Content="Add Label" HorizontalAlignment="Left" Margin="293,490,0,0" VerticalAlignment="Top" Width="75" RenderTransformOrigin="0.518,-0.709" Command="{Binding Path=NewLabelBtn}" />
<TextBlock x:Name="FilesProcessedBlck" HorizontalAlignment="Left" Margin="54,507,0,0" TextWrapping="Wrap" Text="{Binding FilesProcessedBlck, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Top" RenderTransformOrigin="-0.7,0.562" Width="65"/>
</Grid>
ViewModel部分:
public class P4LabelBatteryViewModel : BindableBase
{
private P4LabelBatteryModel p4LabelBatteryModel = new P4LabelBatteryModel();
public P4LabelBatteryViewModel()
{
P4LabelBatteryModel p4LabelBatteryModel = new P4LabelBatteryModel();
this.GetBatteryBtn = new DelegateCommand(chooseFile, canChooseFile);
this.NewLabelBtn = new DelegateCommand(chooseNewLabel, canNewLabel).ObservesProperty(() => NewLabel);
this.FilesProcessedBlck = 2; //this works.
}
//other code here
private void chooseNewLabel()
{
if (ScriptCollection.Count > 0)
{
ScriptCollection = P4LabelBatteryModel.TagsFilesModel(NewLabel, ScriptCollection);
}
}
private int _filesProcessedBlck;
public int FilesProcessedBlck
{
get
{
return _filesProcessedBlck;
}
set
{
SetProperty(ref _filesProcessedBlck, value);
}
}
private ObservableCollection<ScriptModel> _scriptCollection = new ObservableCollection<ScriptModel>();
public ObservableCollection<ScriptModel> ScriptCollection
{
get
{
return _scriptCollection;
}
set
{
SetProperty(ref _scriptCollection, value);
}
}
}
模型部分:
class P4LabelBatteryModel
{
public static ObservableCollection<ScriptModel> TagsFilesModel(string NewLabel, ObservableCollection<ScriptModel> observableCollection)
{
string newLabel = NewLabel;
var scriptsToTagColl = observableCollection;
string[] files = null;
var _p4LabelBatteryViewModel = new P4LabelBatteryViewModel();
_p4LabelBatteryViewModel.FilesProcessedBlck++; //xaml is never updated with this value.
//This will generate an IPC when returned
ObservableCollection<ScriptModel> newCollection = new ObservableCollection<ScriptModel>();
//code here that modifies newCollection xaml updates when this returns, _p4LabelBatteryViewModel.FilesProcessedBlck++; does not.
return newCollection;
}
}
当我运行调试器时,我可以看到正在修改P4LabelBatteryViewModel.FilesProcessedBlck但是没有更新XAML。
答案 0 :(得分:2)
var _p4LabelBatteryViewModel = new P4LabelBatteryViewModel();
_p4LabelBatteryViewModel.FilesProcessedBlck++; //xaml is never updated with this value.
好的,所以你的XAML必须有viewmodel的副本,如果TextBlock
首先显示你期望的那样。但是在这个方法中,你创建了一个相同的viewmodel类的新实例,在它上面设置了一个属性,然后你就什么都不用了。它超出范围,垃圾收集器最终吃掉它。它从来就不是任何视图的DataContext,因此当然它对UI没有任何影响。
_p4LabelBatteryViewModel
是一个局部变量。除了那种方法之外没有人能够看到它甚至知道它存在。如果要更改实际显示在UI中的视图模型的副本,则必须更改该实例。另外,请不要使用_
为本地变量添加前缀。按照惯例,前导下划线表示属于某个类的私有字段。坚持这个惯例是最好的,以避免混淆。
viewmodel应该更新自己的FilesProcessedBlck
属性。在任何情况下,模型都不负责维护视图模型的状态,这不是一个好主意。那是视图模型的问题,让他来处理它。
private void chooseNewLabel()
{
if (ScriptCollection.Count > 0)
{
ScriptCollection = P4LabelBatteryModel.TagsFilesModel(NewLabel, ScriptCollection);
++FilesProcessedBlck;
}
}
在模型中......
public static ObservableCollection<ScriptModel> TagsFilesModel(string NewLabel, IList<ScriptModel> scriptsToTagColl)
{
string newLabel = NewLabel;
string[] files = null;
// This will generate an IPC when returned
ObservableCollection<ScriptModel> newCollection = new ObservableCollection<ScriptModel>();
//code here that modifies newCollection xaml updates when this returns, _p4LabelBatteryViewModel.FilesProcessedBlck++; does not.
return newCollection;
}
我做了一些其他的小改动来简化TagsFilesModel
。例如,没有理由要求呼叫者传入ObservableCollection<T>
。你可能永远不会有任何理由给它任何其他东西,但是如果你养成了代码中那种灵活性的习惯,它会得到回报。
还有一件事。这是无害的,但值得了解:
<TextBlock
x:Name="FilesProcessedBlck"
HorizontalAlignment="Left"
Margin="54,507,0,0"
TextWrapping="Wrap"
Text="{Binding FilesProcessedBlck}"
VerticalAlignment="Top"
RenderTransformOrigin="-0.7,0.562"
Width="65"
/>
UpdateSourceTrigger=PropertyChanged
在Binding
中没有任何用途。 &#34;来源&#34;绑定的是viewmodel属性; &#34;目标&#34;是UI控件属性。 UpdateSourceTrigger=PropertyChanged
告诉Binding
每当控件属性更改时都会更新viewmodel属性。这看起来很愚蠢,但您也可以将其设置为UpdateSourceTrigger=LostFocus
; TextBox.Text
默认为LostFocus
,因为TextBox
的常见情况是用户输入了一段时间,但您真的不关心更新您的视图模型,直到他完成输入和将焦点转移到另一个控件。更新viewmodel属性可能会产生很多副作用,因此如果每次Text
更改时更新绑定的viewmodel属性,在某些情况下最终会出现病态行为:每次用户键入一个字符时,很多代码都被投入运动,以至于UI陷入困境。因此LostFocus
。
对于这个问题,这一切都是偏离主题的,因为那不是TextBox
。它是TextBlock
,根本无法更新源属性,因此该标志无效。
顺便说一句,&#34; Blck&#34;意思?这是因为它显示在TextBlock
中吗?如果在UI中添加了另一个显示的位置会发生什么,但新的位置是labe;你应该重命名它FilesProcessedBlckAndLbl
吗?最好将其称为FilesProcessedCount
,并使视图模型远离关注UI所做的事情。