- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我被迫在 WPF 应用程序中使用 View First MVVM,我正在努力了解如何让它优雅地工作。
问题的根源在于嵌套 UserControls
.在 MVVM 架构中,每个 UserControl
需要将其 View 模型分配给其 DataContext
,这使绑定(bind)表达式保持简单,而且这也是 WPF 将通过 DataTemplate
生成的任何 View 实例化的方式。 .
但是如果一个 child UserControl
具有父需要绑定(bind)到其自己的 View 模型的依赖属性,那么子 UserControl
有它的DataContext
设置为其自己的 View 模型意味着父 XAML 文件中的“隐式路径”绑定(bind)将解析为 subview 模型而不是父 View 模型。
为了解决这个问题,每个 UserControl
的每个 parent 在应用程序中,默认情况下需要对所有内容使用显式命名绑定(bind)(冗长、丑陋且容易出错),或者必须知道特定控件是否具有其 DataContext
是否设置为自己的 View 模型并使用适当的绑定(bind)语法(这同样容易出错,并且严重违反了基本封装)。
经过几天的研究,我还没有找到一个半体面的解决方案来解决这个问题。我遇到的最接近解决方案的方法是设置 UserControl's
viewmodel 到 UserControl
的内部元素(最上面的 Grid
或其他),这仍然让您在尝试绑定(bind) UserControl
的属性时遇到问题自己到自己的 View 模型! ( ElementName
绑定(bind)在这种情况下不起作用,因为绑定(bind)将在命名元素之前声明,并且 View 模型分配给它的 DataContext
)。
我怀疑没有多少其他人遇到此问题的原因是他们要么使用不存在此问题的 viewmodel first MVVM,要么将 view first MVVM 与改善此问题的依赖注入(inject)实现结合使用。
请问有人有干净的解决方案吗?
更新:
根据要求提供示例代码。
<!-- MainWindow.xaml -->
<Window x:Class="UiInteraction.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:UiInteraction"
Title="MainWindow" Height="350" Width="525"
x:Name="_this">
<Window.DataContext>
<local:MainWindowVm/>
</Window.DataContext>
<StackPanel>
<local:UserControl6 Text="{Binding MainWindowVmString1}"/>
</StackPanel>
</Window>
namespace UiInteraction
{
// MainWindow viewmodel.
class MainWindowVm
{
public string MainWindowVmString1
{
get { return "MainWindowVm.String1"; }
}
}
}
<!-- UserControl6.xaml -->
<UserControl x:Class="UiInteraction.UserControl6" x:Name="_this"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:UiInteraction">
<UserControl.DataContext>
<local:UserControl6Vm/>
</UserControl.DataContext>
<StackPanel>
<!-- Is bound to this UserControl's own viewmodel. -->
<TextBlock Text="{Binding UserControlVmString1}"/>
<!-- Has its value set by the UserControl's parent via dependency property. -->
<TextBlock Text="{Binding Text, ElementName=_this}"/>
</StackPanel>
</UserControl>
namespace UiInteraction
{
using System.Windows;
using System.Windows.Controls;
// UserControl code behind declares DependencyProperty for parent to bind to.
public partial class UserControl6 : UserControl
{
public UserControl6()
{
InitializeComponent();
}
public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
"Text", typeof(string), typeof(UserControl6));
public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
}
}
namespace UiInteraction
{
// UserControl's viewmodel.
class UserControl6Vm
{
public string UserControlVmString1
{
get { return "UserControl6Vm.String1"; }
}
}
}
System.Windows.Data Error: 40 : BindingExpression path error: 'MainWindowVmString1' property not found on 'object' ''UserControl6Vm' (HashCode=44204140)'. BindingExpression:Path=MainWindowVmString1; DataItem='UserControl6Vm' (HashCode=44204140); target element is 'UserControl6' (Name='_this'); target property is 'Text' (type 'String')
MainWindow.xaml
声明
<local:UserControl6 Text="{Binding MainWindowVmString1}"/>
正在尝试解决
MainWindowVmString1
在
UserControl6Vm
.
UserControl6.xaml
注释掉
DataContext
的声明和第一个
TextBlock
代码可以工作,但
UserControl
需要一个
DataContext
.在
MainWIndow1
使用
ElementName
代替隐式路径绑定(bind)也可以,但为了使用
ElementName
绑定(bind)语法,您要么必须知道
UserControl
将其 View 模型分配给其
DataContext
(封装失败)或替代采用
ElementName
的策略到处绑定(bind)。两者都没有吸引力。
最佳答案
一个直接的解决方案是使用 RelativeSource
并将其设置为查找 DataContext
parent 的UserControl
:
<UserControl>
<UserControl.DataContext>
<local:ParentViewModel />
</UserControl.DataContext>
<Grid>
<local:ChildControl MyProperty="{Binding DataContext.PropertyInParentDataContext, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}"/>
</Grid>
</UserControl>
"Parent"
拥有对父级的引用的属性,由父级itelf在创建时注入(inject),可以授予对父级的直接访问权限。
public class ParentViewModel : INotifyPropertyChanged
{
#region INotifyPropertyChanged values
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
if (this.PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
private ChildViewModel childViewModel;
public ChildViewModel ChildViewModel
{
get { return this.childViewModel; }
set
{
if (this.childViewModel != value)
{
this.childViewModel = value;
this.OnPropertyChanged("ChildViewModel");
}
}
}
}
<UserControl>
<UserControl.DataContext>
<local:ParentViewModel />
</UserControl.DataContext>
<Grid>
<local:ChildControl DataContext="{Binding ChildViewModel}"
MyProperty1="{Binding PropertyInTheChildControlledByParent}"
MyProperty2="{Binding Parent.PropertyWithDirectAccess}"/>
</Grid>
</UserControl>
DataContext
提供给 child
UserControl
使用附加属性。我还没有完全实现它,但它包含一个附加属性来请求该功能(类似于
"HasAccessToParentDT"
),其中
DependencyPropertyChanged
事件您将连接负载和
Unload
ChildUserControl
的事件, 访问
Parent
属性(在加载控件时可用)并绑定(bind)其
DataContext
到第二个附加属性,
"ParentDataContext"
,然后可以在 xaml 中使用。
<local:ChildControl BindingHelper.AccessParentDataContext="True"
MyProperty="{Binding BindingHelper.ParentDataContext.TargetProperty}" />
关于wpf - View-First-MVVM 中的用户控件和 View 模型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14442418/
我已经对这个主题进行了一些研究,并且已经在少数应用程序中使用了 MVVM 模式。 我问这个问题是因为有时 MVVM 被称为设计,有时被称为架构模式。 在大多数情况下,MVVM 模式称为设计模式。但是就
我开始使用 MVVM Light 版本 4,但我无法理解: 为什么要使用 DataService 和 IDataService? 我应该为模型中的任何类创建数据服务吗? 最佳答案 首先 - 像往常一样
是否可以采用MVVM在一个平台(如 windows phone)中设计模式并以可移植到其他平台(如 android 和 iOS)的方式实现代码的数据绑定(bind)? 或者我最好问问MVVM设计模式在
使用 avalondock在 MVVM 环境中似乎相当具有挑战性。一旦我从 shellview 中分离 DocumentPane,我就会丢失相应的数据上下文并且我的 View 是空的。重新连接时,它会
我对避免背后代码中的代码的方法很感兴趣。 在我看来,有些情况下代码必须放在代码后面。 例如:我有一个未定义列数的网格。无法绑定(bind)列。所以最简单的方法是在后面的代码中生成列。 对于这种情况,我
我熟悉MVVM。实际上,我在SL4中进行了大部分学习。但是,由于最近的需求,我必须使用SL3。我试图将MVVM Light v3与SL3结合使用并利用命令。问题是在SL3中没有按钮的Command属性
UI逻辑在WindowsRT MVVM应用程序中应该在哪里?将其放到ViewModel上真的很“胖”,我想我们失去了MVVM模式的优势之一-在设计人员和程序员之间分配工作变得非常困难。但是,我创建了一
您好,我有 3 个关于 MVVM 模型的问题。 有没有办法绕过那个多余的PropertyChanged("PropName"); 将 POCO 对象包装到 WPF 的最佳方法是什么 INotifyPr
我正在使用 MVVM 模型做一个 Silverlight,我发现很难通过 MVVM 进行事件处理,尤其是事件处理程序在 View 中进行了大量更改,例如启用和禁用按钮、更新媒体元素功能和位置。我还是
我有一个测试应用程序来测试 windows phone 8.1 上的导航,我可以从主页到第二页进入第二页。 问题是,当我单击后退按钮时,我返回桌面屏幕并且应用程序进入后台,所以我必须按住后退按钮才能返
我正在尝试使用并选择好的MVVM Framework,并且其中有很多,因此选择确实很困难。 我想知道其中的2个-CinchV2(Sacha Barber)和MVVM Light Toolkit(Lau
我完全不熟悉Windows 8开发,现在遇到使用MVVM Light混合触摸和键盘导航的问题。 所以,我有个 View 模型的列表,在网格 View 和只要选择其中的一个,导航到选定的 View 模型
我最近下载了MVVMExtraLite,并且有一个名为 Mediator 的帮助程序。我听说过 Messenger (在MVVM Light中)。有什么区别吗? 最佳答案 他们使用相同的模式,即调解员
我正在尝试学习MVVM,并且在区分模型和 View 模型方面有些挣扎。 如果有人可以回答这两个问题,那么对我来说将大有帮助: 说我有一个Objects类,这是一个包含Object的多个Observab
我已经在网上进行了一些研究,并且得出了一些矛盾的答案。这是我的情况: 我有一个引用ClientViewModel的EditClient View ,还有一个还引用ClientViewModel的Add
我正在使用带有 ModelView-First 方法的 MVVM 模式。到目前为止,这工作正常。 现在我有一个用户控件( View ),它应该根据位于我的 ViewModel 中的属性显示各种内容。
我必须创建一个对话框,其中必须在运行时生成列,之前我使用的是 WPF 数据网格,因此在运行时生成列不是问题。现在我必须使用 View 模型,我需要为要在 View 中显示为列的任何字段具有属性。列数在
所以我目前正在使用 Xamarin.Forms 开发一个应用程序。 Xamarin Forms 使用 MVVM 模式,我觉得使用这种模式有点舒服,但我确实有一些问题。为了简单起见,我将使用一个单页应用
是否有在MVVM应用程序中使用Autofac的示例?我不确定在MVVM环境中如何控制生命周期和对象处置。 我知道我可以创建一个生命周期并从其下解决,但这确实更像是服务定位器模式而不是IoC模式。 最佳
我想我遗漏了一些简单的东西,但我找不到任何例子来说明如何做到这一点......另外,如果我使用的某些术语是错误的,请原谅我。 我只想使用绑定(bind)到 Kendo Observable 对象的 H
我是一名优秀的程序员,十分优秀!