- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
好的,我现在有一个更具体的问题。
我试图弄清楚当两个文本框不再为空时如何更改标签的值( bool 值)。我似乎无法弄清楚如何让它工作,即使它看起来很简单。
有人能指出我正确的方向吗?
请看下面我的代码。
模型(Person.cs)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PracticeUI.Model
{
public class Person
{
private string _firstName;
private string _lastName;
public string FullName
{
get
{
return _firstName + " " + _lastName;
}
set { }
}
public string FirstName
{
get
{
return _firstName;
}
set
{
_firstName = value;
}
}
public string LastName
{
get
{
return _lastName;
}
set
{
_lastName = value;
}
}
}
}
using PracticeUI.Model;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
namespace PracticeUI.ViewModel
{
public class PersonViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private Person _newPerson = new Person();
private ICommand _addPerson;
public Person NewPerson
{
get
{
return _newPerson;
}
set
{
_newPerson = value;
OnPropertyChanged("NewPerson");
}
}
public PersonViewModel()
{
_PersonList.Add(new Person() { FirstName = "Tom", LastName = "Barratt" });
_PersonList.Add(new Person() { FirstName = "Harriet", LastName = "Hammond" });
}
private ObservableCollection<Person> _PersonList = new ObservableCollection<Person>();
public ObservableCollection<Person> PersonList
{
get
{
return _PersonList;
}
set
{
_PersonList = value;
OnPropertyChanged("PersonList");
OnPropertyChanged("AddPersonCanExecute");
}
}
public void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
public ICommand AddPersonCommand
{
get
{
if (_addPerson == null)
{
_addPerson = new RelayCommand(p => this.AddPersonCanExecute, p => this.AddPerson());
}
return _addPerson;
}
}
public bool AddPersonCanExecute
{
get
{
return _newPerson.FirstName != string.Empty || _newPerson.LastName != string.Empty;
}
}
public void AddPerson()
{
_PersonList.Add(new Person() { FirstName = _newPerson.FirstName, LastName = _newPerson.LastName });
OnPropertyChanged("PersonList");
}
}
}
<Window x:Class="PracticeUI.View.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ViewModel="clr-namespace:PracticeUI.ViewModel"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<ViewModel:PersonViewModel x:Key="ViewModel"/>
</Window.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="20"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="20"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="20"/>
</Grid.RowDefinitions>
<ListBox ItemsSource="{Binding Source={StaticResource ViewModel}, Path=PersonList}" Grid.Row="1" Grid.Column="2" Grid.ColumnSpan="3" Height="200" Margin="0 0 0 20">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Label Content="{Binding FirstName}"/>
<Label Content="{Binding LastName}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Label Content="First Name:" Grid.Row="2" Grid.Column="1"/>
<TextBox Text="{Binding Source={StaticResource ViewModel}, Path=NewPerson.FirstName, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" Grid.Row="2" HorizontalAlignment="Left" Grid.Column="2" Height="40" Width="200" Margin="10 5"/>
<Label Content="First Name:" Grid.Row="3" Grid.Column="1"/>
<TextBox Text="{Binding Source={StaticResource ViewModel}, Path=NewPerson.LastName, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" Grid.Row="3" HorizontalAlignment="Left" Grid.Column="2" Height="40" Width="200" Margin="10 5"/>
<Button Command="{Binding Source={StaticResource ViewModel}, Path=AddPersonCommand}" Content="Add Person" Width="120" Height="30" Grid.Row="4" Grid.Column="2"/>
<Label Content="{Binding Source={StaticResource ViewModel}, Path=AddPersonCanExecute, UpdateSourceTrigger=PropertyChanged, Mode=OneWay}" Grid.Row="2" Grid.Column="4"/>
</Grid>
</Window>
最佳答案
一、重命名PersonViewModel
至MainViewModel
.它不是代表一个人的 View 模型,它是整个程序的主要 View 模型。它有一个完整的集合 Person
;一个人怎么样?它不是。很好地命名你的类可以更容易地跟踪什么是什么。我们将重命名 Person
至PersonViewModel
因为它也需要是一个 View 模型,而且它确实代表了一个人。
您希望 UI 查看 AddPersonCanExecute
的值每当 NewPerson.FirstName
的值发生变化时或 NewPerson.LastName
.
什么会导致这些值发生变化?
一种方法是 NewPerson
可以换。所以:
public Person NewPerson
{
get
{
return _newPerson;
}
set
{
_newPerson = value;
OnPropertyChanged(nameof(AddPersonCanExecute));
OnPropertyChanged(nameof(NewPerson));
}
}
FirstName
的文本框中键入新值。和
LastName
NewPerson
的属性.那么你和 UI 都不走运了,因为
Person
不是 View 模型。当其属性发生变化时,它从不引发任何事件。所以让它成为一个 View 模型。
public class ViewModelBase : INotifyPropertyChanged
{
// Copy your INotifyPropertyChanged implementation here from your main viewmodel
// Make your main viewmodel inherit from ViewModelBase
}
// Formerly PersonViewModel
public class MainViewModel : ViewModelBase
{
// We need this to be the actual type because we'll need to be calling
// RaiseCanExecuteChanged() on it. Or whatever equivalent.
private RelayCommand _addPerson;
// All the stuff PersonViewModel had.
// Stuff
// Stuff
// Stuff
}
// Remember, your old PersonViewModel is now named MainViewModel. This is the class
// that you used to call Person.
public class PersonViewModel : ViewModelBase
{
public string FullName
{
get
{
return _firstName + " " + _lastName;
}
// No empty set, not ever. Somebody will try to set FullName and the compiler
// will let him think it worked. But nothing will change. That's a bug.
//set { }
}
public string FirstName
{
get
{
return _firstName;
}
set
{
_firstName = value;
// Do the same for LastName. Careful you don't pass nameof(FirstName)
// over there.
OnPropertyChanged(nameof(FirstName));
OnPropertyChanged(nameof(FullName));
}
}
Person
的通知,这是可以解决的。我们必须再次重写 NewPerson:
private PersonViewModel _newPerson = null;
public PersonViewModel NewPerson
{
get { return _newPerson; }
set
{
if (value != _newPerson)
{
// Take the handler off the old NewPerson, if any.
if (_newPerson != null)
{
_newPerson.PropertyChanged -= NewPerson_PropertyChanged;
}
_newPerson = value;
if (_newPerson != null)
{
_newPerson.PropertyChanged += NewPerson_PropertyChanged;
}
OnPropertyChanged(nameof(NewPerson));
OnPropertyChanged(nameof(AddPersonCanExecute));
// I don't know what your RelayCommand class looks like, but it should
// provide some way to force it to raise its CanExecuteChanged event.
// That's what the Button is waiting for to enable or disable itself.
_addPerson.RaiseCanExecuteChanged()
}
}
}
private void NewPerson_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
switch (e.PropertyName)
{
case nameof(Person.FirstName):
case nameof(Person.LastName):
OnPropertyChanged(nameof(AddPersonCanExecute));
AddPerson
break;
}
}
<Window.DataContext>
<ViewModel:PersonViewModel />
</Window.DataContext>
<Window.Resources>
<!-- remove it from here -->
</Window.Resources>
<TextBox
Text="{Binding NewPerson.FirstName, UpdateSourceTrigger=PropertyChanged}"
Grid.Row="2"
HorizontalAlignment="Left"
Grid.Column="2"
Height="40" Width="200" Margin="10 5"
/>
UpdateSourceTrigger=PropertyChanged
仅在 TextBox.Text 上:这将导致文本框在每次击键时更新 View 模型,而不是仅在文本框失去焦点时更新 View 模型属性的默认行为。你不需要
UpdateSourceTrigger=PropertyChanged
在命令绑定(bind)或 Label.Content 绑定(bind)上,因为这些属性永远无法更新 viewmodel 属性。默认情况下,它们是 OneWay,而且它们的工作性质也是如此。
关于c# - WPF MVVM : Update label depending on Textbox input (2nd Attempt),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58304844/
这个问题在这里已经有了答案: How to automatically select all text on focus in WPF TextBox? (33 个答案) How to select
我在我的项目中使用了以下模板:
我有一个非常奇怪的问题。我有多个用于用户名/密码的文本框,每个用户/密码组旁边都有一个复选框。当用户单击 CheckBox 时,如果他选中它,它旁边的用户名和密码 TextBox 将被启用,焦点将设置
我有两个带有这样的日期选择器的文本框。 $(function () { $('#value_date').datetimepicker({ format: 'MM/DD/YY
我检查了大约 60 个国家/地区的邮政编码。用户输入邮政编码,根据该国家/地区的规则进行检查。美国是个异常(exception),我可以根据已输入的其他街道地址信息自动填写值。在某些方面,它基本上是一
我们的应用程序启动几个后台进程并将它们的输出放入 TextBoxes - 每个在 TabControl 中的一个单独的 TabItem。我希望 TextBoxes 自动滚动以显示最后一个输出行,因此在
TextBlock 元素很好地处理了 LineHeight,允许文本完全显示,而无需剪切。但是,我想将其更改为 TextBox 以方便编辑文本,这就是我的麻烦开始的地方。 TextBlock 显示如下
我正在尝试“帮助”用户表单上文本输入框的用户输入百分比。 截至目前,我的输入框将任何输入转换为百分比形式。这意味着键入“6”会将值转换为 600%。如下所示 databaseViewer 是输入框从中
我有一个带有 RichEditBox 的 Windows 应用商店应用程序(编辑)和一个 Grid (边注)。 我需要始终匹配两个元素的垂直滚动位置。这样做的目的是允许用户在文档的页边空白处添加注释。
我有一个问题。下面的代码用于通过 .append() 和 .remove() 动态添加和删除文本框。我希望占位符为 textbox 的文本框中的所有数据都会内爆,并放置在我设置的名称为 textbox
我有一个文本框,其 Text 属性具有 TwoWay MultiBinding,UpdateSourceTrigger 设置为 属性已更改。第一个 Binding 是一个依赖属性 (Value),它具
它们之间有什么区别吗?谢谢 TextBox.Clear(); TextBox.Text = string.Empty; 最佳答案 在实践中:不。在内部,有。两者都以完全不同的方式清除文本。 我不敢告
这两种方法有什么区别? 一个比另一个更有效率吗? 我在想 AppendText() 可能使用类似于 StringBuilder 的方法,即它使用自己的缓存而不是每次都创建和附加一个新字符串,是这样吗?
我有一个文本框来显示一个很长的 Base64 字符串。 TextBox.Multline = true 和 TextBox.WordWrap = true。 此问题是由文本框本身的自动字边界检测引起的
在 this document在描述 Windows 10 UWP 应用程序的生命周期时,它指出: Users now expect your app to remember its state as
我需要检查如果我的 TextBox (txtmoney) 为空或等于 0,则不允许按 0 键键盘或数字 0。 我该怎么做? 最佳答案 Before implementing please refer
我有一个显示一些 TextBoxes 的 ListView。对于每个 TextBox,我都会捕获一个 SelectionChanged 事件。 我的 XAML 文件看起来像这样:
当我单击(或双击)Access 表单的文本框时,我需要选择其中的所有文本。我尝试了以下代码,但没有成功: Me.txt_CompraPreco.SelStart = 0 Me.txt_CompraPr
我有一个 ListView(在更新面板中)绑定(bind)到一个 ObjectDataSource(连接到一个 NHibernate 对象)并且在 EditItemTemplate 我使用 Text=
我正在尝试使用 D3 绘制多条交互式线条。单击每一行时,应根据当前鼠标坐标显示一个 float 文本框,并等待输入更新行坐标。更改文本框后,该行应自动更新,文本框应消失。有人可以看看我的代码并找出问题
我是一名优秀的程序员,十分优秀!