如何在这种特定的 WPF 情况下应用 MVVM 和命令?

发布于 2024-08-18 15:24:32 字数 2140 浏览 8 评论 0原文

我在使用 WPF 应用程序中的 MVVM 模式和命令时遇到问题。问题不在于 MVVM 模式,而在于我的 GUI 上发生的事情。我将解释这种情况:

我的应用程序可以对某些文件进行 DoStuff。我有一个带有函数 DoStuff(int limit) 的类。我的用户界面具有以下项目:

  • 用于开始解析的 Button DoStuffBtn
  • 用于填写限制的 TextBox LimitTxt
  • 用于启用或禁用限制的 CheckBox LimitChk

当您“取消选中”LimitChk 时,请选择 LimitTxt.Text = ""LimitTxt.IsEnabled = false。当您“检查”LimitChk 时,然后再次 LimitTxt.IsEnabled = false,但文本仍为空,直到您填写一些内容。

我已经阅读了许多有关 WPF 中命令的教程和 MVVM,但我似乎无法将我的案例倒入那个模具中。我给出的例子实际上只是我的用户界面的一小部分,但我似乎也不能很好地做到这一点。

我不断遇到这样的问题:

  • LimitChk 需要两个 Command(启用和禁用)还是只需要一个(切换)?
  • 如果我将 int 绑定到 LimitTxt,如果我将其清空并禁用它,会发生什么情况?
  • 当按下 DoStuffBtn 时,仅使用 DoStuff(Int32.Parse(LimitTxt.Text)) 是一种干净的方法吗?
  • 如果我在 LimitChk 上使用两个命令,则 ICommandCanExecute() 函数会发生什么情况来确定 LimitChk已启用?

所以主要问题是:我所描述的情况如何适合使用 WPF 中的命令的良好模式?

我查看过有关 WPF、命令和 MVVM 的一些链接:


到目前为止我的理解是我必须尽可能远离用户界面。甚至像 UI 这样的东西也会影响 UI。即取消选中 LimitChk 会禁用 LimitText。尽管如此,我认为我应该在 UI 相关信息和操作以及实际上与必须完成的实际工作有关的内容之间保持区别。

I am having trouble with the MVVM pattern and Commands in my WPF app. The problem is not so much the MVVM pattern, but more the stuff that is going on on my GUI. I'll explain the situation:

My app can DoStuff to some files. I have a class with a function DoStuff(int limit). My user user interface has the following items:

  • A Button DoStuffBtn to start parsing.
  • A TextBox LimitTxt to fill in a limit.
  • A CheckBox LimitChk to enabled or disable the limit.

When you would "uncheck" LimitChk, then LimitTxt.Text = "" and LimitTxt.IsEnabled = false. When you would "check" LimitChk, then LimitTxt.IsEnabled = false again, but the text remains empty until you fill something in.

I have read many tutorials on Commands in WPF and MVVM but I just can't seem to pour my case into that mold. The example I gave is actually just a small part of my UI, but I can't seem to do this nicely either.

I keep running into questions like:

  • Do I need two Commands for LimitChk (enable and disable) or just one (toggle)?
  • If I bind an int to LimitTxt, what happens if I make it empty and disable it?
  • Is it a clean way to just use DoStuff(Int32.Parse(LimitTxt.Text)) when DoStuffBtn is pressed?
  • If I use two commands on LimitChk, what happens with the CanExecute() function of ICommand that determines whether LimitChk is enabled?

So the main question is: How would the situation I described fit into a nice pattern using Commands in WPF?

Some links on WPF, Commands and MVVM i've looked at:


What I understand so far is that I have to keep as much as possible out of the UI. Even stuff like UI influencing the UI. I.e. unchecking LimitChk disables LimitText. Still, I think I should keep a difference between UI related information and actions and stuff that actually has to do with the actual work that has to be done.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

一江春梦 2024-08-25 15:24:32

我认为您很困惑...这里不需要任何命令,您只需使用绑定即可。

  • 我需要两个 LimitChk 命令(启用和禁用)还是只需要一个命令(切换)?

你不需要。只需在 ViewModel 中创建一个 LimitEnabled 属性,并将 CheckBox 绑定到它 (IsChecked="{Binding LimitEnabled}")

  • 如果我将一个 int 绑定到 LimitTxt,如果将其设置为空并禁用它会发生什么?

禁用它没有任何影响。如果将 TextBox 设为空,则绑定将失败,因为空字符串无法转换为 int(至少使用默认转换器无法转换)

  • 按下 ParseBtn 时仅使用 Parse(Int32.Parse(LimitTxt.Text)) 是一种干净的方法吗?

你不需要。只需在 ViewModel 中创建一个 Limit 属性,并将 TextBox 绑定到它即可。您可能需要将 ExceptionValidationRule 添加到 Binding 中,以便突出显示无效输入。

该按钮不是必需的,当 TextBox 失去焦点时,解析将自动完成(如果您使用默认的 UpdateSourceTrigger)。如果您想自定义其解析方式,您可以创建一个自定义转换器以在绑定中使用。

I think you're getting confused... you don't need any commands here, you can just use bindings.

  • Do I need two Commands for LimitChk (enable and disable) or just one (toggle)?

You need none. Just create a LimitEnabled property in your ViewModel, and bind the CheckBox to it (IsChecked="{Binding LimitEnabled}")

  • If I bind an int to LimitTxt, what happens if I make it empty and disable it?

Disabling it has no effect. If you make the TextBox empty, the binding will fail because an empty string can't be converted to an int (at least not with the default converter)

  • Is it a clean way to just use Parse(Int32.Parse(LimitTxt.Text)) when ParseBtn is pressed?

You don't need to. Just create a Limit property in your ViewModel, and bind the TextBox to it. You might want to add an ExceptionValidationRule to the Binding so that it highlights invalid input.

The button is not necessary, the parsing will be done automatically when the TextBox loses focus (if you use the default UpdateSourceTrigger). If you want to customize the way it's parsed, you can create a custom converter to use in the binding.

や三分注定 2024-08-25 15:24:32

只是一些高层次的想法,省略诸如颜色和​​对齐属性、WrapPanels 等多余的东西。

您的 ViewModel 有几个属性:

public bool? LimitIsChecked { get; set; }
public bool LimitTextIsEnabled { get; set; }  //to be expanded, below
public ICommand ParseCommand { get; private set; } // to be expanded, below
public string LimitValue { get; set; } // further explanation, below

您的 XAML 有 CheckBox 和 TextBox 定义,例如:

<CheckBox Content="Limit Enabled" IsChecked="{Binding LimitIsChecked}" />
<TextBox Text="{Binding LimitValue}" IsEnabled="{Binding LimitIsEnabled}" />
<Button Content="Parse" Command="{Binding ParseCommand}" />

您需要初始化 ParseCommand,如下所示:

this.ParseCommand = new DelegateCommand<object>(parseFile);

现在,让我们也填写 LimitTextIsEnabled 属性:

public bool LimitTextIsEnabled {
    // Explicit comparison because CheckBox.IsChecked is nullable.
    get { return this.LimitIsChecked == true; }
    private set { }
}

您的 parseFile 方法会将 LimitValue 属性的值传递给执行实际解析的逻辑。

我在此处将 LimitValue 属性声明为字符串,以避免显式转换器或其他验证代码使代码变得混乱。您可以选择以几种不同的方式处理“LimitValue is a valid int”验证/转换。

当然,我还没有完全实现这一点,但我想概述一种模式,在这种模式中,您不使用命令来更新其他小部件的状态。相反,请将这些属性绑定到 ViewModel 中管理的属性。

Just some high level thoughts, leaving out superfluous stuff like Color and alignment attributes, WrapPanels, etc.

Your ViewModel has a a couple properties:

public bool? LimitIsChecked { get; set; }
public bool LimitTextIsEnabled { get; set; }  //to be expanded, below
public ICommand ParseCommand { get; private set; } // to be expanded, below
public string LimitValue { get; set; } // further explanation, below

Your XAML has CheckBox and TextBox definitions something like:

<CheckBox Content="Limit Enabled" IsChecked="{Binding LimitIsChecked}" />
<TextBox Text="{Binding LimitValue}" IsEnabled="{Binding LimitIsEnabled}" />
<Button Content="Parse" Command="{Binding ParseCommand}" />

You'll want to initialize ParseCommand something like this:

this.ParseCommand = new DelegateCommand<object>(parseFile);

Now, let's fill in that LimitTextIsEnabled property too:

public bool LimitTextIsEnabled {
    // Explicit comparison because CheckBox.IsChecked is nullable.
    get { return this.LimitIsChecked == true; }
    private set { }
}

Your parseFile method would then pass the value of the LimitValue property to the logic doing the actual parsing.

I declared the LimitValue property as string here to avoid cluttering up the code with an explicit converter, or other validation code. You could choose to handle that "LimitValue is a valid int" verification/conversion in several different ways.

Of course, I haven't implemented this in its entirety, but I wanted to outline a pattern where you are not using Commands to update the state of the other widgets. Instead, bind those attributes to properties that are managed in your ViewModel.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文