WPF新手绑定问题

问题描述 投票:0回答:1

我刚刚在 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>
wpf data-binding
1个回答
0
投票

首先,你不能分配像

DataContext.Count += 1
这样的值,因为
DataContext
object
类型,它不会实现
Count
属性,即使分配的对象是
ClickCount
类型,我建议你研究一下 OOP 中的多态性。您可以将
DataContext
转换为
ClickCount
类型,而不是您尝试的方法,如下所示
((ClickCount)DataContext).Count += 1
。您可以在这里找到有关类型转换的更多信息:转换和类型转换

但通常您希望通过 MVVM 中的命令来实现此行为,因此您可以创建

ICommand
接口(通常称为
RelayCommand
)的实现,然后将其放入类中
,而不是显示代码ClickCount
并将命令绑定到 XAML 中
Command
Button
属性。有关更多信息,您可以查看此处MVVM - Commands、RelayCommands 和 EventToCommand

为了减少行数,您可以实现一个抽象类,所有视图模型(

DataContext
)都会继承该抽象类,或者更确切地说,您可以使用一些已经实现了此功能的 Nuget。我个人喜欢 Community MVVM Toolkit,其中包含接口
INotifyPropertyChanged
ObservableObject
以及用于调用
SetProperty
事件的
PropertyChanged
方法)和
ICommand
(
RelayCommand
) 的实现。

最后,如果您在

Label
中指定
ContentStringFormat
,则可以使用单个
Label
,如下所示:
<Label Content="{Binding Count}" ContentStringFormat="Count: {0}"/>
。这里还提到:WPF StringFormat on Label Content

希望这有帮助。

© www.soinside.com 2019 - 2024. All rights reserved.