如何使用 DelegateCommand 将信息从 View 传递到 ViewModel?

发布于 2024-07-21 05:13:53 字数 910 浏览 7 评论 0原文

在我的视图中,我有一个按钮。

当用户单击此按钮时,我想让 ViewModel 将 TextBlock 的上下文保存在数据库中。

<StackPanel HorizontalAlignment="Left" VerticalAlignment="Top">
    <TextBlock Text="{Binding FirstName}"/>
    <TextBox Text="Save this text to the database."/>
    <Button Content="Save" Command="{Binding SaveCommand}"/>
</StackPanel>

但是,在 ViewModel 的 DelegateCommand 中,“Save()”方法不传递任何参数,那么此时如何从视图获取数据呢?

#region DelegateCommand: Save
private DelegateCommand saveCommand;

public ICommand SaveCommand
{
    get
    {
        if (saveCommand == null)
        {
            saveCommand = new DelegateCommand(Save, CanSave);
        }
        return saveCommand;
    }
}

private void Save()
{
    TextBox textBox = ......how do I get the value of the view's textbox from here?....
}

private bool CanSave()
{
    return true;
}
#endregion

In my View, I have a button.

When the user clicks this button, I want to have the ViewModel save the context of the TextBlock in the database.

<StackPanel HorizontalAlignment="Left" VerticalAlignment="Top">
    <TextBlock Text="{Binding FirstName}"/>
    <TextBox Text="Save this text to the database."/>
    <Button Content="Save" Command="{Binding SaveCommand}"/>
</StackPanel>

However, in my DelegateCommand in my ViewModel, the "Save()" method doesn't pass any arguments, so how do I get data from the view at that point?

#region DelegateCommand: Save
private DelegateCommand saveCommand;

public ICommand SaveCommand
{
    get
    {
        if (saveCommand == null)
        {
            saveCommand = new DelegateCommand(Save, CanSave);
        }
        return saveCommand;
    }
}

private void Save()
{
    TextBox textBox = ......how do I get the value of the view's textbox from here?....
}

private bool CanSave()
{
    return true;
}
#endregion

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

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

发布评论

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

评论(6

清醇 2024-07-28 05:13:53

请查看 Josh Smith 撰写的这篇 MSDN 文章。 在其中,他展示了 DelegateCommand 的一个变体,他将其称为 RelayCommand,并且 RelayCommand 上的 Execute 和 CanExecute 委托接受对象类型的单个参数。

使用 RelayCommand,您可以通过 CommandParameter 将信息传递给委托人:

<Button Command="{Binding SaveCommand}" 
        CommandParameter="{Binding SelectedItem,Element=listBox1}" />

更新

查看 这篇文章,似乎有一个通用版本的 DelegateCommand,它以类似的方式接受参数。 您可能想要尝试将 SaveCommand 更改为 DelegateCommand 并更改 Save 和 CanSave 方法,以便它们采用 MyObject 参数。

Check out this MSDN article by Josh Smith. In it, he shows a variation of DelegateCommand that he calls RelayCommand, and the Execute and CanExecute delegates on RelayCommand accept a single parameter of type object.

Using RelayCommand you can pass information to the delegates via a CommandParameter:

<Button Command="{Binding SaveCommand}" 
        CommandParameter="{Binding SelectedItem,Element=listBox1}" />

Update

Looking at this article, it appears that there is a generic version of DelegateCommand which accepts a parameter in a similar way. You might want to try changing your SaveCommand to a DelegateCommand<MyObject> and change your Save and CanSave methods so that they take a MyObject parameter.

像极了他 2024-07-28 05:13:53

这是优雅的方式。

为文本框命名,然后将按钮中的 CommandParameter 绑定到其 Text 属性:

<StackPanel HorizontalAlignment="Left" VerticalAlignment="Top">
    <TextBlock Text="{Binding FirstName}"/>
    <TextBox x:Name="ParameterText" Text="Save this text to the database."/>
    <Button Content="Save" Command="{Binding SaveCommand}"
            CommandParameter="{Binding Text, ElementName=ParameterText}"/>
</StackPanel>

here is the elegant way.

Give a name to your textbox, then bind the CommandParameter in the button to it's Text property:

<StackPanel HorizontalAlignment="Left" VerticalAlignment="Top">
    <TextBlock Text="{Binding FirstName}"/>
    <TextBox x:Name="ParameterText" Text="Save this text to the database."/>
    <Button Content="Save" Command="{Binding SaveCommand}"
            CommandParameter="{Binding Text, ElementName=ParameterText}"/>
</StackPanel>
深巷少女 2024-07-28 05:13:53

在您的虚拟机中:

private DelegateCommand<string> _saveCmd = new DelegateCommand<string>(Save);

public ICommand SaveCmd{ get{ return _saveCmd } }

public void Save(string s) {...}

在您的视图中,像 Matt 的示例一样使用 CommandParameter。

In your VM:

private DelegateCommand<string> _saveCmd = new DelegateCommand<string>(Save);

public ICommand SaveCmd{ get{ return _saveCmd } }

public void Save(string s) {...}

In you View, use CommandParameter like Matt's example.

初与友歌 2024-07-28 05:13:53

您询问的是通过按钮命令传递数据。

我认为,您真正想要的是将 Textbox 的文本绑定到 ViewModel 中的公共属性

<!-- View: TextBox's text is bound to the FirstName property in your ViewModel -->
<TextBox Text="{Binding Path=FirstName}" />
<Button Command="{Binding SaveCommand}"/>

<!-- ViewModel: Expose a property for the TextBox to bind to -->
public string FirstName{ get; set; }
...
private void Save()
{
    //textBox's text is bound to --> this.FirstName;
}

You're asking about passing data via the button Command.

What you actually want, I think, is to bind your Textbox's text to a public property in your ViewModel:

<!-- View: TextBox's text is bound to the FirstName property in your ViewModel -->
<TextBox Text="{Binding Path=FirstName}" />
<Button Command="{Binding SaveCommand}"/>

<!-- ViewModel: Expose a property for the TextBox to bind to -->
public string FirstName{ get; set; }
...
private void Save()
{
    //textBox's text is bound to --> this.FirstName;
}
浅唱ヾ落雨殇 2024-07-28 05:13:53

我想我还没有被允许发表评论。 我回应卡洛斯的建议是因为我尝试过。 虽然这是一个好主意,但 DelegateCommand 需要以某种方式进行修改,否则您会收到此错误:
字段初始值设定项无法引用非静态字段、方法或属性“MyViewModel.Save(string)”。

I'm not allowed to make comments yet, I guess. I'm responding to Carlos' suggestion because I tried it out. While it's a great idea, DelegateCommand would need to be modified in some way because otherwise you'll get this error:
A field initializer cannot reference the non-static field, method, or property 'MyViewModel.Save(string)'.

燃情 2024-07-28 05:13:53

网格内的文本块,在视图中绑定:

                            <telerik:GridViewDataColumn Header="Anunciante">
                            <telerik:GridViewDataColumn.CellTemplate>
                                <DataTemplate>
                                    <Grid Background="{Binding AnuncianteColor}" Margin="0,7,0,7" VerticalAlignment="Center"  >
                                        <TextBlock Text="{Binding Anunciante}" 
                                                   Padding="5,10,5,10" 
                                                   HorizontalAlignment="Stretch" 
                                                   TextAlignment="Center"
                                                   Tag="{Binding Index}"
                                                   MouseDown="AnuncianteMouseDown" />
                                    </Grid>
                                </DataTemplate>
                            </telerik:GridViewDataColumn.CellTemplate>
                        </telerik:GridViewDataColumn>

以及一个隐藏的按钮,用于隐藏命令

<Button Visibility="Collapsed" x:Name="AnunciantedoubleClick" Command="{Binding AnuncianteClickCommand}"></Button>

代码,

        private void AnuncianteMouseDown(object sender, MouseButtonEventArgs e) 
    {
        //if (e.ClickCount == 2)
        //{
            this.AnunciantedoubleClick.Command.Execute(((TextBlock)sender).Tag);
        //}
    }

最后在 ModelView 中进行代码:

public ICommand AnuncianteClickCommand { get; }

在构造函数中:

this.AnuncianteClickCommand = new DelegateCommand<object>(this.AnuncianteClickDelegate);

并且委托显示一条带有行索引的消息(自定义消息框服务,抱歉)

        private void AnuncianteClickDelegate(object v) 
    {
        MessageBoxService.Show(v.ToString());
    }

textblock inside grid, binding in view:

                            <telerik:GridViewDataColumn Header="Anunciante">
                            <telerik:GridViewDataColumn.CellTemplate>
                                <DataTemplate>
                                    <Grid Background="{Binding AnuncianteColor}" Margin="0,7,0,7" VerticalAlignment="Center"  >
                                        <TextBlock Text="{Binding Anunciante}" 
                                                   Padding="5,10,5,10" 
                                                   HorizontalAlignment="Stretch" 
                                                   TextAlignment="Center"
                                                   Tag="{Binding Index}"
                                                   MouseDown="AnuncianteMouseDown" />
                                    </Grid>
                                </DataTemplate>
                            </telerik:GridViewDataColumn.CellTemplate>
                        </telerik:GridViewDataColumn>

and a hidden button biding for command

<Button Visibility="Collapsed" x:Name="AnunciantedoubleClick" Command="{Binding AnuncianteClickCommand}"></Button>

code behind

        private void AnuncianteMouseDown(object sender, MouseButtonEventArgs e) 
    {
        //if (e.ClickCount == 2)
        //{
            this.AnunciantedoubleClick.Command.Execute(((TextBlock)sender).Tag);
        //}
    }

and finally code in ModelView:

public ICommand AnuncianteClickCommand { get; }

in a constructor:

this.AnuncianteClickCommand = new DelegateCommand<object>(this.AnuncianteClickDelegate);

and the delegate shows a message with the row index (custom messagebox service, sorry)

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