RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1583093
Accepted
ikikaidesu
ikikaidesu
Asked:2024-06-07 21:23:15 +0000 UTC2024-06-07 21:23:15 +0000 UTC 2024-06-07 21:23:15 +0000 UTC

如何通过视图更新WPF MVVM中的数据?

  • 772

我有textbox

            <TextBox Text="{Binding DisplayNickName}"
                     Style="{StaticResource enternickname}"
                     Margin="10,10,0,0"/>

他的风格中有一个按钮。我希望当我单击用户的昵称时,在文件和模型中更新用户的昵称,但我不知道该怎么做。尝试解决我添加到Model方法中的问题

public void update_nick(string nickname)
        {
            // обновляем в файле
            JsonData.set_name(nickname);
            // устанавливаем ник в model
            this.nickname = nickname;
        }

之后我想在虚拟机中发出命令,但不幸的是我不知道传入数据到底要采取什么(联系什么来获取它)并且我现在陷入了这一点,所以我希望更有经验的人提供帮助,我到底应该在VM中联系什么才能将数据输入到文本框中(我的想法是DisplayNickName)以及如何在样式中指定命令?一种风格

<!--Добавим текст бокс-->
<TextBox 
    Text="{TemplateBinding Text}"
    Background="Transparent"
    BorderThickness="0"
    Foreground="#deddd0"
    FontSize="20"
    Margin="1,0,0,0"
    x:Name="NameBox"
    MaxLength="15"
    Width="auto"/>
<!--Кнопка подтвеждения никнейма-->
<Button VerticalAlignment="Center"
        HorizontalAlignment="Right"
        Background="Transparent"
        BorderThickness="0"
        Cursor="Hand"
        Command="{Binding DataContext.UpdateNicknameCommand, RelativeSource={RelativeSource AncestorType=Window}}"
        CommandParameter="{Binding Text, ElementName=NameBox}">
    <Image Source="/images/check_mark.png" Width="25" Height="25"/>
    <!--Добавил в стиль кнопки триггеры для того чтобы она выводилась только при вводе и чтобы фон не менялся-->
    <Button.Style>
        <Style TargetType="{x:Type Button}">
            <Setter Property="Background" Value="Transparent" />
            <Setter Property="Visibility" Value="Collapsed"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Button}">
                        <Border x:Name="Border" Background="{TemplateBinding Background}">
                            <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
                        </Border>
                        <ControlTemplate.Triggers>
                            <DataTrigger Binding="{Binding IsKeyboardFocused, ElementName=NameBox}" Value="True">
                                <Setter Property="Visibility" Value="Visible"/>
                            </DataTrigger>
                            <Trigger Property="IsMouseOver" Value="True">
                                <Setter Property="Background" Value="Transparent" TargetName="Border" />
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Button.Style>
</Button>

更改昵称的命令及命令方法

public ICommand ChangeNickNameCommand { get; set; }
private void ChangeNickName(object obj)
{
    if (obj is string nickname)
    {
        _accountModel.update_nick(nickname);
    }
}

来自带有绑定的构造函数的一段代码

    // привязываем команду
    ChangeNickNameCommand = new RelayCommand(ChangeNickName);

I命令码

class RelayCommand : ICommand
{
    private readonly Action<object> _execute;
    private readonly Func<object, bool> _canExecute;
    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }
    public RelayCommand(Action<object> execute, Func<object, bool> canExecute = null)
    {
        _execute = execute;
        _canExecute = canExecute;
    }
    public bool CanExecute(object parameter) => _canExecute == null || _canExecute(parameter);
    public void Execute(object parameter) => _execute(parameter);
}
c#
  • 1 1 个回答
  • 37 Views

1 个回答

  • Voted
  1. Best Answer
    EvgeniyZ
    2024-06-07T22:32:38Z2024-06-07T22:32:38Z

    让我解释一下我在评论中所说的话。

    现在,您拥有了一种“样式”,它不包含一个特定控件的类型,而是包含一组不同控件的一种大杂烩。这种方法不方便、缺乏支持且难以管理。首先,你需要解决这个问题。嗯,在帮助下就可以简单地解决UserControl。

    简单的例子

    • 右键单击项目中的项目/文件夹,然后选择“添加”>“用户控制”>指定名称>“添加”。我个人只会称呼它TestControl。

    • 工作室将为我们生成2个文件,XAML并且CS(一切都像窗口一样)。

    • 打开.cs并添加 2 个包含必要数据的属性。在我们的例子中,这是一个需要命令的按钮,我们还以显示标题为例。

    • 实际上,我们propdp在构造函数之后编写并单击TAB,工作室会亲切地为我们创建代码,调整它以适合我们自己,设置必要的类型和名称。结果,我们得到这样的结果:

      public partial class TestControl : UserControl
      {
          public TestControl()
          {
              InitializeComponent();
          }
      
          public ICommand Command
          {
              get => (ICommand)GetValue(CommandProperty);
              set => SetValue(CommandProperty, value);
          }
          public string Title
          {
              get => (string)GetValue(TitleProperty);
              set => SetValue(TitleProperty, value);
          }
      
          public static readonly DependencyProperty CommandProperty =
              DependencyProperty.Register("Command", typeof(ICommand), typeof(TestControl), new PropertyMetadata(default));
      
          public static readonly DependencyProperty TitleProperty =
              DependencyProperty.Register("Title", typeof(string), typeof(TestControl), new PropertyMetadata(default));
      
      }
      
    • 接下来,打开它XAML并在其中写入所需的设计。这里有一个关于绑定的重要点:控件没有DataContext,所有绑定通常都是通过名称或类似的机制进行的,所以一开始我们会设置控件x:Name(我通常简单地写uc)。结果,我们得到以下标记:

      <UserControl
          x:Class="WPF_net.TestControl"
          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:local="clr-namespace:WPF_net"
          xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
          x:Name="uc"
          d:DesignHeight="450"
          d:DesignWidth="800"
          mc:Ignorable="d">
          <StackPanel Margin="8">
              <TextBlock
                  Margin="0,5"
                  FontWeight="Medium"
                  Text="{Binding Title, ElementName=uc}" />
              <Grid>
                  <Grid.ColumnDefinitions>
                      <ColumnDefinition />
                      <ColumnDefinition Width="Auto" />
                  </Grid.ColumnDefinitions>
                  <TextBox x:Name="textBox" Grid.Column="0" />
                  <Button
                      Grid.Column="1"
                      Command="{Binding Command, ElementName=uc}"
                      CommandParameter="{Binding Text, ElementName=textBox}"
                      Content="Отправить" />
              </Grid>
          </StackPanel>
      </UserControl>
      
      • 正如我所说,这里的关键是通过控件本身的名称进行绑定。另请注意CommandParameter,根据您的想法(据我了解),您希望TextBox使用类似的绑定将输入的文本传递给命令(同样,我们按名称查找所需的控件并获取其属性),我们将单击按钮时将输入的文本传递给命令。
    • 您现在就可以使用它。打开一个窗口并在那里写入<namespace:ИмяКонтрола Свойства = "Значения" />,在我的例子中它将如下所示:<local:TestControl Title="Супер контрол с кнопкой"/>

    • 工作室会一直抱怨,直到我们成功组装该项目,这就是我们实际所做的,重建它并启动它。在屏幕上我们会看到这样的东西

    用户控制结果

    恭喜您获得第一个用户控件。有了它,你现在可以启动 MVVM...

    MVVM、数据传输、绑定

    实际上,我们现在的任务是通过单击按钮将输入的数据接收到虚拟机中,然后将其发送到模型,而模型又必须在那里执行某些操作。

    • 我们编写Model,让它成为一个简单的类,它将把输入的行添加到文件中。我会尽可能简化,但我想你会理解本质......

      public class FileModel
      {
          public string Path { get; } = "TestFile.txt";
      
          public Task AddToFileAsync(string text)
              => File.AppendAllTextAsync(Path, text);
      }
      
    • 现在我们编写ViewModel,它的任务很简单,使用命令从按钮获取文本并将其发送到模型。让它是这样的:

      public partial class MainViewModel : ObservableObject
      {
          private readonly FileModel _fileModel;
      
          public MainViewModel()
          {
              _fileModel = new();
          }
      
          [RelayCommand]
          private async Task Send(string text)
          {
              await _fileModel.AddToFileAsync(text);
          }
      }
      
      • 看到这里你可能会感到惊讶,这个奇怪的代码是什么,这是什么RelayCommand,这是什么partial等等ObservableObject?我很懒(我建议你这样做),我将这些ICommand等的所有实现都交给了INotifyPropertChanged“代码生成器”。如果你有兴趣,就研究一下CommunityToolkit.Mvvm,如果没有,就手动写一下;网上有很多这方面的例子。
    • 剩下的就是将命令绑定到窗口XAML并将其设置到DataContext窗口。我们在 XAML 中编写一个绑定到我们的控件的命令,然后我们得到<local:TestControl Title="Супер контрол с кнопкой" Command="{Binding SendCommand}"/>.好吧,我们将窗口设置DataContext为MainViewModel(我将其写在构造函数中DataContext = new MainViewModel();,但你不应该这样做)。

    • 让我们启动并尝试一下。单击时,将创建一个文件,并向其中添加一个新行,该行写入用户控件文本字段中。

    结果

    这实际上是一个最简单、基本的项目示例,根据 MVVM 规则,具有绑定,甚至具有自己的控制。

    • 1

相关问题

  • 使用嵌套类导出 xml 文件

  • 分层数据模板 [WPF]

  • 如何在 WPF 中为 ListView 手动创建列?

  • 在 2D 空间中,Collider 2D 挂在玩家身上,它对敌人的重量相同,我需要它这样当它们碰撞时,它们不会飞向不同的方向。统一

  • 如何在 c# 中使用 python 神经网络来创建语音合成?

  • 如何知道类中的方法是否属于接口?

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    我看不懂措辞

    • 1 个回答
  • Marko Smith

    请求的模块“del”不提供名为“default”的导出

    • 3 个回答
  • Marko Smith

    "!+tab" 在 HTML 的 vs 代码中不起作用

    • 5 个回答
  • Marko Smith

    我正在尝试解决“猜词”的问题。Python

    • 2 个回答
  • Marko Smith

    可以使用哪些命令将当前指针移动到指定的提交而不更改工作目录中的文件?

    • 1 个回答
  • Marko Smith

    Python解析野莓

    • 1 个回答
  • Marko Smith

    问题:“警告:检查最新版本的 pip 时出错。”

    • 2 个回答
  • Marko Smith

    帮助编写一个用值填充变量的循环。解决这个问题

    • 2 个回答
  • Marko Smith

    尽管依赖数组为空,但在渲染上调用了 2 次 useEffect

    • 2 个回答
  • Marko Smith

    数据不通过 Telegram.WebApp.sendData 发送

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5