WPF将数据从视图传递到UserControl中的ViewModel

huangapple go评论65阅读模式
英文:

WPF Pass data from View to ViewModel in UserControl

问题

以下是您要翻译的内容:

我有一个名为 ListBox 的控件,其中包含一个由 Note Model(主题、文本、ID)表示的笔记列表(NoteList):

<ListBox x:Name="NotesListBox" ItemsSource="{Binding NoteList}">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <UserControls:NoteHeadControl/>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

我在单独的 UserControlNoteHeadControl)中创建了一个 ListItem。决定通过 Tag 属性传递 ID。我不确定这是否是最佳方式,但我不知道其他方法。

<Button Name="OpenButton" Tag="{Binding id}">
    <DockPanel>
        <Label Content="{Binding subject}"/>
        <Button Command="{Binding DeleteNoteCommand}" Name="DeleteNoteButton" Content="Delete"/>
    </DockPanel>
</Button>

对于 NoteHeadControl,我创建了单独的 ViewModelNoteHeadControlViewModel),其中包含我的命令和属性。例如,我想在笔记上创建一个 DELETE 按钮,以从数据库中删除它。为此,NoteHeadControlViewModel 需要 ID 参数。

当我尝试从 View 传递数据到 ViewModel 时出现问题:

public NoteHeadControl()
{
    InitializeComponent();

    NoteHeadControlViewModel noteHeadControlViewModel = new NoteHeadControlViewModel((int)this.OpenButton.Tag);
    DataContext = noteHeadControlViewModel;
}

似乎在运行 (int)this.OpenButton.Tag 时,UserControl 尚未完全初始化,因此 OpenButton 未找到(为 null)。

问题是,我如何从 Window -> UserControl -> UserControlViewModel 传递数据(在我的情况下是 ID)?

我尝试在 Button 而不是 UserControl 控制器中设置 Tag 属性。UserControl 已初始化,但属性仍然为 null

这个任务有很多步骤,我的许多决定看起来有点奇怪(我仍在学习,大多数决策来自这里或其他资源),所以我不知道我犯了哪个最大的错误或者我自己解决问题时缺少了什么知识。

英文:

I have ListBox with list of notes (NoteList) that represented by the Note Model (subject, text, id):

&lt;ListBox x:Name=&quot;NotesListBox&quot; ItemsSource=&quot;{Binding NoteList}&quot;&gt;
                &lt;ListBox.ItemTemplate&gt;
                    &lt;DataTemplate&gt;
                        &lt;UserControls:NoteHeadControl/&gt;
                    &lt;/DataTemplate&gt;
                &lt;/ListBox.ItemTemplate&gt;
            &lt;/ListBox&gt;

ListItem I created in separate UserControl (NoteHeadControl). Was decided to pass Id by Tag property. I`m not sure that it is the best way of doing this, but I don't know how to do it other way.

    &lt;Button Name=&quot;OpenButton&quot; Tag=&quot;{Binding id}&quot;&gt;
        &lt;DockPanel&gt;
            &lt;Label Content=&quot;{Binding subject}&quot;/&gt;
            &lt;Button Command=&quot;{Binding DeleteNoteCommand}&quot; Name=&quot;DeleteNoteButton&quot; Content=&quot;Delete&quot;/&gt;
        &lt;/DockPanel&gt;
    &lt;/Button&gt;

For NoteHeadControl I created separate ViewModel (NoteHeadControlViewModel
) where my commands and properties should be. For example, I want to create a DELETE button on note to delete it from my database. For this Id parameter is required in NoteHeadControlViewModel.

The problem happens when I try to pass Id data from View to ViewModel:

    public NoteHeadControl()
    {
        InitializeComponent();

        NoteHeadControlViewModel noteHeadControlViewModel = new NoteHeadControlViewModel((int)this.OpenButton.Tag);
        DataContext = noteHeadControlViewModel;
    }

It seems that UserControl is not completely initialized at the moment when (int)this.OpenButton.Tag is run and OpenButton is just not found (null).

The question is, how can I pass data (Id in my case) from Window -> UserControl -> UserControl`s ViewModel ?

I tried to set Tag property not in the Button, but in UserControl controller. UserControl is initialized, but the property is still null.

This task has so many steps and so many of my decision looks kind of strange (I`m still learning and most of them I found here or on other resources) so I don't know where I have done the biggest mistake or what I don't know to resolve the issue by myself.

答案1

得分: 1

>对于NoteHeadControl,我创建了一个单独的ViewModel(NoteHeadControlViewModel),其中包含我的命令和属性。

这是错误的。UserControl不应该有自己的视图模型。它应该继承来自父元素的DataContext。

您可以将一个ICommand依赖属性添加到NoteHeadControl,并将其绑定到应负责删除该项的父视图模型的命令:

<UserControls:NoteHeadControl DeleteCommand="{Binding DataContext.DeleteNoteCommand, 
    RelativeSource={RelativeSource AncestorType=ListBox}}" CommandParameter="{Binding}" />

然后,在控件中,您可以将Button的Command属性绑定到依赖属性:

<Button Command="{Binding DeleteCommand, RelativeSource={RelativeSource AncestorType=UserControl}}" 
        Content="Delete"/>

但请不要通过显式设置控件的DataContext来中断DataContext的继承,就像这样:

NoteHeadControlViewModel noteHeadControlViewModel = new NoteHeadControlViewModel((int)this.OpenButton.Tag);
DataContext = noteHeadControlViewModel;
英文:

>For NoteHeadControl I created separate ViewModel (NoteHeadControlViewModel ) where my commands and properties should be.

This is wrong. The UserControl should not have its own view model. It should inherit the DataContext from the parent element.

What you can do is to add an ICommand dependency property to the NoteHeadControl and bind this one to a command of the parent view model that should be responsible for deleting the item:

&lt;UserControls:NoteHeadControl DeleteCommand=&quot;{Binding DataContext.DeleteNoteCommand, 
    RelativeSource={RelativeSource AncestorType=ListBox}}&quot; CommandParameter=&quot;{Binding}&quot; /&gt;

In the control, you then bind the Command property of the Button to the dependency property:

&lt;Button Command=&quot;{Binding DeleteCommand, RelativeSource={RelativeSource AncestorType=UserControl}}&quot; 
        Content=&quot;Delete&quot;/&gt;

But don't break the DataContext inheritance by explicitly setting the DataContext of the control like this:

NoteHeadControlViewModel noteHeadControlViewModel = new NoteHeadControlViewModel((int)this.OpenButton.Tag);
DataContext = noteHeadControlViewModel;

huangapple
  • 本文由 发表于 2023年5月17日 20:57:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/76272374.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定