【问题标题】:WPF Passing multiple parameters to viewmodel (Easily)WPF将多个参数传递给viewmodel(轻松)
【发布时间】:2017-05-16 19:43:32
【问题描述】:

我正在使用 MVVM 模式,但我发现 WPF 使用起来过于复杂。每个小任务都需要多行代码。我遇到了一个非常简单的问题,我需要解决。但是我发现的每条指令(转换器,多重绑定......)对于这样一个极其简单的任务来说似乎都太复杂了。这是一个插图:

当单击“Svar”按钮时,“对象 a”(类型 object)和对象 b(类型 string)应发送到 ViewModel。我已经实现了ICommand 并且传递列表项是可行的,但似乎只是传递更多信息突然需要额外的数十行代码。你们将如何处理这项任务?

更新: 一些代码。视图模型:

class ViewModelMain : ViewModelBase
{
    public object _selectedItem { get; set; }
    ICommand _answer;

    public void AnalyzeAnswer(MemEntity memEntity)
    {
        if(ReviewService.IsCorrectAnswer("", memEntity))
        Console.Beep(1000, 200);
    }

    public ICommand Answer
    {
        get
        {
            if (_answer == null)
            {
                _answer = new RelayCommand(
                    p => true,
                    p => this.AnalyzeAnswer((MemEntity)p));
            }
            return _answer;
        }
    }

    public ObservableCollection<MemEntity> items { get; set; }

    public object SelectedItem
    {
        get
        {
            return _selectedItem;
        }
        set
        {
            Console.Beep(1000, 200);
            _selectedItem = value;
            OnPropertyChanged("SelectedItem");
        }
    }

    public ViewModelMain()
    {
        items = new ObservableCollection<MemEntity> {
        new MemEntity { Word1 = "a", Correct = 3, Incorrect = 1 },
        new MemEntity { Word1 = "b", Correct = 1, Incorrect = 0 },
        new MemEntity { Word1 = "c", Correct = 30, Incorrect = 5 }
    };
}

查看:

<Grid>
    <ListBox x:Name="items" SelectedItem="{Binding SelectedItem, Mode=TwoWay, NotifyOnTargetUpdated=True, NotifyOnSourceUpdated=True}" HorizontalAlignment="Left" Height="266" Margin="10,35,0,0" VerticalAlignment="Top" Width="174" ItemsSource="{Binding items}" DisplayMemberPath="Word1"/>
    <TextBlock HorizontalAlignment="Left" Margin="189,35,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="138" Text="{Binding SelectedItem.Word1}"/>
    <ProgressBar HorizontalAlignment="Left" Height="14" Margin="189,212,0,0" VerticalAlignment="Top" Width="138" Value="{Binding SelectedItem.Proficiency, Mode=OneWay}" Foreground="#FF0672B0"/>
    <TextBox HorizontalAlignment="Left" Height="20" Margin="189,75,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="138" RenderTransformOrigin="-0.025,0.478"/>
    <Button Command="{Binding Path=DoSomethingCommand}" CommandParameter="{Binding SelectedItem}" Content="Svar" HorizontalAlignment="Left" Margin="331,75,0,0" VerticalAlignment="Top" Width="78"/>
    <Label Content="Statistikk" HorizontalAlignment="Left" Margin="189,181,0,0" VerticalAlignment="Top" Width="138"/>
    <Label Content="3 korrekt og 2 feil" HorizontalAlignment="Left" Margin="189,226,0,0" VerticalAlignment="Top" Width="108"/>
    <ToolBarTray HorizontalAlignment="Left" VerticalAlignment="Top" Width="517">
        <ToolBar VerticalAlignment="Top" Margin="0,0,-79,0">
            <Button Content="Lagre" VerticalAlignment="Top" />
            <Button Content="Åpne" VerticalAlignment="Top"/>
        </ToolBar>
    </ToolBarTray>
    <StatusBar HorizontalAlignment="Left" Height="24" Margin="0,306,0,0" VerticalAlignment="Top" Width="517"/>
</Grid>

【问题讨论】:

  • 如果您需要“发送到视图模型”,您可能不会使用 mvvm 方式。该表单上的所有内容都应该绑定到视图模型属性,并且您的命令应该只对这些属性的值起作用。如果您需要通知应用程序的其他部分,请发送带有模型的消息。要获得具体答案,您需要显示一些代码。
  • 我应该使用的词是绑定。我正在使用命令,并尽力使用 MVVM。当说“发送”时,我指的是 CommandParameter 的形式。

标签: c# wpf mvvm


【解决方案1】:

1) 如果您的SelectedItem 是MemEntity,请将其声明为MemEntity,而不是object;

2) 将 TextBox.Text 属性绑定到 ViewModel 中的字符串属性;

3) 将命令绑定到不带参数的简单Action,在其中调用object 和string;

4) 使用 C#-6.0 nameof 功能引发属性更改通知。

类似这样的:

public class ViewModelMain : ViewModelBase
{
    public ViewModelMain()
    {
        Items = new ObservableCollection<MemEntity> {
            new MemEntity { Word1 = "a", Correct = 3, Incorrect = 1 },
            new MemEntity { Word1 = "b", Correct = 1, Incorrect = 0 },
            new MemEntity { Word1 = "c", Correct = 30, Incorrect = 5 }
        };
    }

    public ICommand Answer
    {
        get
        {
            if (_answer == null)
            {
                _answer = new RelayCommand(
                    p => true,
                    p => AnalyzeAnswer());
            }
            return _answer;
        }
    }
    private ICommand _answer;

    public void AnalyzeAnswer()
    {
        //use SelectedItem and Text in this method,
        //you don't need to pass them as parameters
    }

    public string Text { get; set; }

    public ObservableCollection<MemEntity> Items { get; set; }

    public MemEntity SelectedItem
    {
        get
        {
            return _SelectedItem;
        }
        set
        {
            Console.Beep(1000, 200);
            _SelectedItem = value;
            OnPropertyChanged(nameof(SelectedItem));
        }
    }
    private MemEntity _SelectedItem;
}

在 xaml 中,将布局属性分开(边距、大小等),Button 将是:

<Button Command="{Binding Path=DoSomethingCommand}"
        Content="Svar"/>

还有TextBox:

<TextBox Text="{Binding Path=Text}"/>

没有最简单快捷的方法。 MVVM 可能看起来很冗长,但它是以下要求的最低要求:

  1. 将 UI 与逻辑解耦;
  2. 将这两者松散地绑定在一起;
  3. 为您提供所需的所有功能。

【讨论】:

  • 现在我明白了。感谢您提供代码示例和如此详尽的答案。是的,WPF 一开始可能有点让人不知所措,但我正在慢慢掌握它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-08
  • 2021-08-31
  • 2021-07-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多