Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# MVVM-带参数的行为或查找特定的父/用户控制资源_C#_Wpf_Mvvm - Fatal编程技术网

C# MVVM-带参数的行为或查找特定的父/用户控制资源

C# MVVM-带参数的行为或查找特定的父/用户控制资源,c#,wpf,mvvm,C#,Wpf,Mvvm,所以,我对MVVM还相当陌生,我已经回到了一个有趣的角落,我不知道如何使用行为或命令使事情正常工作。我有一个用户控件,其中包含一个项目列表框,需要实现各种行为,例如删除或删除给定项目。像这样: <UserControl> // DataContext is a viewmodel // Borders, grids, various nesting controls... <ListBox x:Name="ListBox_Items" ItemSource="{

所以,我对MVVM还相当陌生,我已经回到了一个有趣的角落,我不知道如何使用行为或命令使事情正常工作。我有一个用户控件,其中包含一个项目列表框,需要实现各种行为,例如删除或删除给定项目。像这样:

<UserControl> // DataContext is a viewmodel
    // Borders, grids, various nesting controls...
    <ListBox x:Name="ListBox_Items" ItemSource="{Binding ItemsList}">
        <ListBox.ItemTemplate>
            <DataTemplate> // From here on the individual item has its own data context of type Item in ItemsList
                <StackPanel Orientation="Horizontal">
                    <TextBox Name="EditItemStuffOnLoseFocus" Text="{Binding ItemStuff}"/>
                    <Button Name="DeleteItemStuff"/>
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
</UserControl>
当然,这个消息框并不是以应用程序为中心的,虽然小,但很烦人。一位同事建议我用一个行为替换命令,这样我就可以有一个关联的对象用于将消息框居中。问题是,我无法找到有关将参数传递给行为的任何信息,也无法找到如何将多个级别从关联对象追溯到其父对象的信息,以便获得重载步骤的视图模型以及单个项的模型(关联对象的DataContext)

总之,有没有一种方法可以在保持MVVM友好的同时将MessageBox集中在命令中的应用程序上,或者使用行为传递参数/检索特定的父对象或其资源

____________更新____________

下面的答案很好,但我采用了另一种方法,以便在MessageBox中使用DataContext变量。通过将视图模型添加到控件的标记中,我成功地保留了对调用控件和视图模型的DataContext的访问:

<UserControl> // DataContext is a viewmodel
    // Borders, grids, various nesting controls...
    <ListBox x:Name="ListBox_Items" ItemSource="{Binding ItemsList}">
        <ListBox.ItemTemplate>
            <DataTemplate> // From here on the individual item has its own data context of type Item in ItemsList
                <StackPanel Orientation="Horizontal">
                    <TextBox Name="EditItemStuffOnLoseFocus" Text="{Binding ItemStuff}" Tag={Binding RelativeSource={RelativeSource AncestorType=ListBox}, Path=DataContext}"/>
                    <Button Name="DeleteItemStuff" Tag={Binding RelativeSource={RelativeSource AncestorType=ListBox}, Path=DataContext}"/>
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
</UserControl>

谢谢大家的帮助。

要在窗口上居中显示消息框,您需要实现自己的窗口,并执行一个可指定位置的显示对话框。或者,您可以从中完成的Forms控件继承

然而,对于问题的第一部分,在按钮上实现一个click处理程序并将delete作为依赖属性绑定到用户控件可能会更容易。这将允许您访问发送方并将UI完全保留在控件内

xaml


只需从外部绑定delete命令,并在click事件中为消息框执行逻辑

要在窗口上居中显示消息框,您需要实现自己的窗口,并执行ShowDialog,您可以在其中指定位置。或者,您可以从中完成的Forms控件继承

然而,对于问题的第一部分,在按钮上实现一个click处理程序并将delete作为依赖属性绑定到用户控件可能会更容易。这将允许您访问发送方并将UI完全保留在控件内

xaml


只需从外部绑定delete命令,并在click事件中为消息框执行逻辑

谢谢你的回复!我看到了解决方案如何使用FrameworkElement在不破坏MVVM的情况下传递按钮的DataContext,但我仍然希望它不依赖于背后的代码(主要是因为我真的希望在消息框消息中显示一些DataContext信息,而不会使代码与所使用的模型有太多的关联)。我将再等一段时间,然后查看代码项目解决方案。我认为您是正确的,但是范例是,视图确实知道有关viewmodel的一些信息。这就是为什么我们静态地声明绑定。如果您希望使信息尽可能松散耦合,我建议让viewmodel从nd接口,该接口将以字符串形式提供数据。另一种选择是,您可以拥有一个附加属性,该属性绑定到您希望传递的字符串,然后您可以在代码隐藏中获取该附加属性。我不确定您是否要摆脱代码隐藏。最终,您将转到另一个路径以保留viewModel access,但我要将此标记为答案,因为它适用于发布的问题。我还将更新我的问题,以提供我使用的解决方法,以防它对其他人有帮助。感谢您的回答!我看到了解决方案如何使用FrameworkElement传递按钮的数据上下文而不破坏MVVM,但我仍然希望它能够不依赖代码隐藏(主要是因为我确实希望在消息框消息中显示一些DataContext信息,而不会使代码隐藏与所使用的模型有太多的联系)。我将再等一段时间,然后查看代码项目解决方案。我认为您是正确的,但是范例是,视图确实知道有关viewmodel的一些信息。这就是为什么我们静态地声明绑定。如果您希望使信息尽可能松散耦合,我建议让viewmodel从nd接口,该接口将以字符串形式提供数据。另一种选择是,您可以拥有一个附加属性,该属性绑定到您希望传递的字符串,然后您可以在代码隐藏中获取该附加属性。我不确定您是否要摆脱代码隐藏。最终,您将转到另一个路径以保留viewModel access,但我要将此标记为答案,因为它适用于发布的问题。我还将更新我的问题,以提供我使用的解决方法,以防它对其他人有帮助。我不确定这对您的解决方案来说是否过份,但我一直在WPF应用程序中对任何类型的弹出窗口使用自定义UserControl。如果你有兴趣尝试这种方法,或者我可以把它写下来作为一个完整的答案,并详细说明它是如何实现的。我不确定这对你的解决方案来说是否太过分了,但我一直在我的WPF应用程序中对任何类型的弹出窗口使用自定义用户控件。如果你有兴趣尝试这种方法,我会发布我使用的代码,或者我可以把它写下来作为一个完整的答案,更详细地说明它是如何实现的。
<UserControl> // DataContext is a viewmodel
    // Borders, grids, various nesting controls...
    <ListBox x:Name="ListBox_Items" ItemSource="{Binding ItemsList}">
        <ListBox.ItemTemplate>
            <DataTemplate> // From here on the individual item has its own data context of type Item in ItemsList
                <StackPanel Orientation="Horizontal">
                    <TextBox Name="EditItemStuffOnLoseFocus" Text="{Binding ItemStuff}" Tag={Binding RelativeSource={RelativeSource AncestorType=ListBox}, Path=DataContext}"/>
                    <Button Name="DeleteItemStuff" Tag={Binding RelativeSource={RelativeSource AncestorType=ListBox}, Path=DataContext}"/>
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
</UserControl>
ExampleViewModel viewModel = (ExampleViewModel)AssociatedObject.Tag;
Item parameter = (Item)AssociatedObject.DataContext;

if (MessageBox.Show(Window.GetWindow(AssociatedObject), "Really delete the item?", "Delete Item", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes)
    {
        ItemService service = new ItemService();
        service.RemoveItem(((Item)parameter).ItemID);

        if (viewModel.ReloadItemListCommand.CanExecute(viewModel.ItemInfo))
            viewModel.ReloadItemListCommand(viewModel.ItemInfo);
    }
}
  <ListBox ItemsSource="{Binding Items}">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <StackPanel>
                    <Label Content="{Binding Name}" />
                    <Button Click="Button_Click" />
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
public ICommand DeleteItem
    {
        get { return (ICommand)GetValue(DeleteItemProperty); }
        set { SetValue(DeleteItemProperty, value); }
    }
public static readonly DependencyProperty DeleteItemProperty = DependencyProperty.Register("DeleteItem", typeof(ICommand), typeof(control), new PropertyMetadata(null));
private void Button_Click(object sender, RoutedEventArgs e)
    {
        if (DeleteItem != null)
        {
            var result = System.Windows.MessageBox.Show("WOULD YOU LIKE TO DELETE?", "Delete", MessageBoxButton.YesNo, MessageBoxImage.Warning);
            if (result == MessageBoxResult.Yes)
            {
                var fe = sender as FrameworkElement;
                if (DeleteItem.CanExecute(fe.DataContext))
                {
                    DeleteItem.Execute(fe.DataContext);
                }
            }
        }