WPF新手绑定问题

6ju8rftf  于 2023-10-22  发布在  其他
关注(0)|答案(2)|浏览(120)

我刚刚在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>
b91juud3

b91juud31#

首先,你不能像DataContext.Count += 1那样赋值,因为DataContext的类型是object,即使赋值对象的类型是ClickCount,它也不会实现Count属性。我建议你在OOP中研究多态性。你可以将DataContext转换为ClickCount类型,就像这样((ClickCount)DataContext).Count += 1。你可以在这里找到更多关于类型转换的信息:转换和类型转换。
但通常您希望通过MVVM中的命令实现此行为。因此,您将创建ICommand接口的实现(通常称为RelayCommand),然后将其放入类ClickCount中,并将命令绑定到XAML中ButtonCommand属性,而不是您所显示的代码。有关更多信息,请参阅MVVM - Commands, RelayCommands and EventToCommand
为了减少行数,你可以实现一个抽象类,所有的视图模型(DataContext)都会继承这个抽象类,或者你可以使用一些已经实现了这个抽象类的Nugets。我个人喜欢Community MVVM Toolkit,它包含接口INotifyPropertyChangedObservableObject,使用SetProperty方法调用PropertyChanged事件)和ICommandRelayCommand)的实现。
最后,如果在Label中指定ContentStringFormat,则可以使用单个Label,如下所示:<Label Content="{Binding Count}" ContentStringFormat="Count: {0}"/>。这里还提到:WPF StringFormat on Label Content

cgh8pdjw

cgh8pdjw2#

在后面的代码中,是否永远无法直接访问DataContext上的属性?
因为DataContext属性的类型是object,所以需要强制转换它。
通常的方法是将DataContext属性设置为视图模型类的示例(查找Model-View-ViewModel(MVVM)设计模式),并执行该类中的任何逻辑,但这是另一回事。
接下来,有没有一种方法可以用更少的代码行实现INotifyPropertyChanged?
您可以使用源代码生成器(如Fody)动态注入代码,在编译时引发PropertyChanged事件。
然后你可以像这样实现你的ClickCount类型:

public class ClickCount : INotifyPropertyChanged
{
    public int Count { get; set; }

    public event PropertyChangedEventHandler PropertyChanged;
}

在.xaml中,有没有一种方法可以合并“Count:“文本和计数值在一个标签?
如果您使用TextBlock而不是Label,则可以使用StringFormat选项:

<TextBlock Text="{Binding Count, StringFormat={}Count: {0}}" />

ContentStringFormat适用于Label,但您通常应该使用TextBlocks来显示文本:

<Label Content="{Binding Count}" ContentStringFormat="Count: {0}"/>

相关问题