我刚刚在WPF中实现了一个点击计数器,我很好奇是否有更好的方法来做这些事情。
完整代码在这里:https://github.com/surferjeff/ClickCount/tree/main/WpfCounter
在后面的代码中,是否永远无法直接访问DataContext
上的属性?我必须让另一个成员另一个成员周围的正确类型?
接下来,有没有一种方法可以用更少的代码行实现INotifyPropertyChanged?
using System.ComponentModel;
using System.Windows;
namespace WpfCounter
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private ClickCount clickCount = new ClickCount();
public MainWindow()
{
InitializeComponent();
DataContext = clickCount;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
// DataContext.clickCount += 1;
// Why does the commented line above fail to compile with the error?
// Error CS1061 'object' does not contain a definition for 'clickCount' and no accessible extension method 'clickCount' accepting a first argument of type 'object' could be found(are you missing a using directive or an assembly reference ?)
clickCount.Count += 1;
}
}
class ClickCount : INotifyPropertyChanged
{
int _count = 0;
public int Count {
get => _count;
set {
_count = value;
PropertyChanged.Invoke(this, new PropertyChangedEventArgs(nameof(Count)));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
}
在.xaml中,有没有一种方法可以合并“Count:“文本和计数值在一个标签?
<Window x:Class="WpfCounter.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:local="clr-namespace:WpfCounter"
mc:Ignorable="d"
Title="MainWindow" Height="300" Width="350">
<Grid>
<StackPanel VerticalAlignment="Center" HorizontalAlignment="Center">
<!-- None of the following work:
<Label HorizontalAlignment="Center" Margin="10,10,10,10" FontSize="20">Count: {Binding Count}</Label>
<Label HorizontalAlignment="Center" Margin="10,10,10,10" FontSize="20">{Binding Count}</Label>
-->
<StackPanel Orientation="Horizontal">
<Label HorizontalAlignment="Center" Margin="10,10,0,10" FontSize="20">Count:</Label>
<Label HorizontalAlignment="Center" Margin="0,10,10,10" FontSize="20" Content="{Binding Count}"/>
</StackPanel>
<Button HorizontalAlignment="Center" FontSize="20" Padding="10,5,10,5" Click="Button_Click">Click Me</Button>
</StackPanel>
</Grid>
</Window>
2条答案
按热度按时间b91juud31#
首先,你不能像
DataContext.Count += 1
那样赋值,因为DataContext
的类型是object
,即使赋值对象的类型是ClickCount
,它也不会实现Count
属性。我建议你在OOP中研究多态性。你可以将DataContext
转换为ClickCount
类型,就像这样((ClickCount)DataContext).Count += 1
。你可以在这里找到更多关于类型转换的信息:转换和类型转换。但通常您希望通过MVVM中的命令实现此行为。因此,您将创建
ICommand
接口的实现(通常称为RelayCommand
),然后将其放入类ClickCount
中,并将命令绑定到XAML中Button
的Command
属性,而不是您所显示的代码。有关更多信息,请参阅MVVM - Commands, RelayCommands and EventToCommand。为了减少行数,你可以实现一个抽象类,所有的视图模型(
DataContext
)都会继承这个抽象类,或者你可以使用一些已经实现了这个抽象类的Nugets。我个人喜欢Community MVVM Toolkit,它包含接口INotifyPropertyChanged
(ObservableObject
,使用SetProperty
方法调用PropertyChanged
事件)和ICommand
(RelayCommand
)的实现。最后,如果在
Label
中指定ContentStringFormat
,则可以使用单个Label
,如下所示:<Label Content="{Binding Count}" ContentStringFormat="Count: {0}"/>
。这里还提到:WPF StringFormat on Label Contentcgh8pdjw2#
在后面的代码中,是否永远无法直接访问DataContext上的属性?
因为
DataContext
属性的类型是object
,所以需要强制转换它。通常的方法是将
DataContext
属性设置为视图模型类的示例(查找Model-View-ViewModel(MVVM)设计模式),并执行该类中的任何逻辑,但这是另一回事。接下来,有没有一种方法可以用更少的代码行实现INotifyPropertyChanged?
您可以使用源代码生成器(如Fody)动态注入代码,在编译时引发
PropertyChanged
事件。然后你可以像这样实现你的
ClickCount
类型:在.xaml中,有没有一种方法可以合并“Count:“文本和计数值在一个标签?
如果您使用
TextBlock
而不是Label
,则可以使用StringFormat
选项:ContentStringFormat
适用于Label
,但您通常应该使用TextBlocks
来显示文本: