为什么我们在处理WPF时会使用MVVM而不是MVC?
使用它可以获得多大的好处?
编辑:
说实话,今天我接受了采访,我被问到这个问题.我的答案像INotifyPropertyChanged,ICommand,IValue Convertor ..但他并不满意.从此我提出了这个问题
提前致谢
我正在使用MVVM模式编写应用程序.我通过将我的视图的DataContext属性设置为我的ViewModel的实例来向我的视图提供数据.一般来说,我只是从那里使用Binding并继续我的方式.
最近,我试图在我的ViewModel提供的"选择项目"的集合之外实现一个带有"额外"元素的ComboBox.
<ComboBox>
<ComboBox.ItemsSource>
<CompositeCollection>
<ComboBoxItem IsEnabled="False">Select Item</ComboBoxItem>
<CollectionContainer Collection="{Binding MyItemsCollection}" />
</CompositeCollection>
</ComboBox.ItemsSource>
</ComboBox>
Run Code Online (Sandbox Code Playgroud)
问题是,CompositeCollection不是Freezable:Freezable Objects Overview.这会导致仅显示静态ComboBoxItem,而不会导致我的绑定表达式产生任何结果.
我对这个问题的第一反应是,只是实现自己CompositeCollection的版本是可冻结.但是,这引出了以下问题:
为什么CompositeCollection首先不是Freezable?
我担心的是,通常这些决定是出于某种原因而做出的,我不觉得我对Freezable的了解不足以说明为什么他们没有从中继承.我知道我可以实现这个系列,但我担心如果我这样做会有一个可衡量的性能差异.
任何帮助,将不胜感激.谢谢!
另外:请注意,我意识到我可以插入Null或其他一些特殊值,并提供模板或valueconverter来做我想要的.这不是我感兴趣的问题......只是上面的粗体问题.
更新:
经过ArsenMkrt的评论进行了一些进一步的研究后,我发现我认为这实际上是一种疏忽.证据如下:
FreezableCollection<T>.我没有生成CollectionViews,这使得它不能直接满足我的需求.我目前解决这个问题的计划是创建一个具有CompositeCollection和属性的新集合FreezableCollection<T>.我不知道它是否还能正常工作,但我正在考虑这样的事情:
public class BindableCompositeCollection : FreezableCollection<object>, ICollectionViewFactory
Run Code Online (Sandbox Code Playgroud)
如果有人有更好的选择,我想听听!
我已经看过像Nerddinner和ContactManager这样的简单应用程序以及像Kigg这样的更复杂的应用程序.我理解更简单的那些,现在我想了解更复杂的那些.
通常,较简单的应用程序在LINQtoSQL或实体框架之上具有存储库类和接口(尽可能松散耦合).从控制器调用存储库以执行必要的数据操作.
我在研究更复杂的应用程序(如Kigg或Oxite)时看到的一个常见模式是引入(我只是在这里搔痒但我必须从某处开始):
这是我的问题:
我知道为了真正拥有一个松散耦合的应用程序,你必须使用像Unity这样的东西.但是,当你将Unity引入混合时,你也必须引入一个Web Request Lifetime Manager.这是为什么?为什么像Nerddinner这样的示例应用程序没有Web请求终身管理器?它到底是做什么用的?这是Unity特定的事情吗?
我注意到的第二种模式是引入工作单元.同样,同样的问题:为什么Nerddinner或ContactManager不使用工作单位?相反,这些应用程序使用Linq2Sql或Entity Framework之上的存储库类来执行数据操作.没有任何工作单位的迹象.究竟是什么以及为什么要使用它?
谢谢
以下是DinnersController级别的Nerddiner中DI的示例:
public DinnersController()
: this(new DinnerRepository()) {
}
public DinnersController(IDinnerRepository repository) {
dinnerRepository = repository;
}
Run Code Online (Sandbox Code Playgroud)
所以我是正确的假设因为第一个构造函数控制器"拥有"DinnerRepository,因此它将依赖于控制器的生命周期,因为它在那里被声明了?
我正在尝试创建一个"文件"任务项组,其中包含一个名为"TargetPath"的元数据属性,其中填充了文件的相对路径.
示例:
对于这些路径:
D:\ Test\Blah.exe
D:\ Test\Config\fun.config
D:\ Test\en-US\my.resources.dll
输出应该是:
文件目标= Blah.exe
文件目标= Config\fun.config
文件目标= en-US\my.resources.dll
这是我最好的尝试...希望这使我的问题更清楚:
<ItemGroup>
<Files Include="d:\test\**\*" >
<TargetPath>%(RecursiveDir)%(Filename)%(Extension)</TargetPath>
</Files>
</ItemGroup>
<Message Text="File Target = @(Files->'%(TargetPath)')"/>
Run Code Online (Sandbox Code Playgroud)
我想正确填充"TargetPath"...目前它似乎为空或空.谁知道我错过了什么?
编辑:
是的,我知道我可以这样做:
<Message Text="File Target = @(Files->'%(RecursiveDir)%(Filename)%(Extension)')"/>
Run Code Online (Sandbox Code Playgroud)
但是,我正在构建此ItemGroup以使用ResolveManifestFiles MSBuild任务,这需要我使用TargetPath元数据属性构建一个TaskItem,以便能够自定义该值.
我公司最近正在做一些WPF和Silverlight开发,我们发现虽然我们擅长吊索代码,但我们的UI设计技巧缺乏一些"pizazz".
微软称之为"devigner"在哪里?是否有这些类型的艺术家/可用性专家的用户组(特别是在达拉斯地区)?
我有使用这些技能的网络开发人员的经验,但没有那么多的WPF/Silverlight经验和在互联网上看这些人没有太多.
编辑:这是一个维基,所以我可以得到更多的反馈,没有人认为我钓鱼积分.到目前为止,评论都很有帮助.
我正在使用zend服务器,我在extra/httpd-vhosts.conf文件中添加了一个VirtualHost,并从httpd.conf文件中删除了#.
这是我在extra/httpd-vhosts.conf文件中添加的内容:
NameVirtualHost *:80
<VirtualHost *:80>
ServerName quickstart.local
DocumentRoot D:/quickstart/Code
<Directory D:/quickstart/Code>
DirectoryIndex index.php
AllowOverride All
Order allow,deny
Allow from all
</Directory>
</VirtualHost>
Run Code Online (Sandbox Code Playgroud)
当我访问quickstart.local它工作正常,但它也影响localhost(即当我尝试加载http:// localhost /时,我看到我为http://quickstart.local/做的同一个站点.
我该如何解决这个问题?我想要localhost(我将其用于另一个项目)和quickstart.local分开.
我想将安装程序包部署到我的客户.我的应用程序基本上是一个网站,但我希望他们能够获得最佳体验.Chrome或Mozilla Prism.我想给他们一个安装程序(win:msi/exe),在桌面上放置一个图标并启动我的应用程序.他们可能已经安装了Chrome,也可能没有安装Firefox.
我做了一些浅薄的搜索,但已经干了.我不能帮助,但我想我不是第一个想要这样做的人.我认为Adobe Air有这样的事情,但我过去曾遇到Air问题.
air windows-installer google-chrome web-applications mozilla-prism
我在我的应用程序中使用System.Windows.Controls.WebBrowser进行各种操作,我注意到当它们应该出现在WebBrowser上时,它们会被切断.我意识到WebBrowser控件实际上是一个COM组件的包装器,可能呈现不同的方式,但我想知道是否有人想出如何解决这个问题.
这是我看到的问题.在这里,我只有一个样本装饰,应该在某个东西的顶角绘制一个大的红色圆圈(作为样本).
当我用这个装饰WebBrowser时,我得到了这个结果:
我希望看到完整的圆圈.
这是这个毫无价值的装饰者的代码,以防有用:
public class SillyAdorner : Adorner
{
public SillyAdorner(UIElement element) : base(element)
{
}
protected override void OnRender(DrawingContext drawingContext)
{
drawingContext.DrawEllipse(new SolidColorBrush(Colors.Red), new Pen(), new Point(7, 7), 30, 30);
base.OnRender(drawingContext);
}
}
Run Code Online (Sandbox Code Playgroud)
以下是我在主机控件的OnRender方法中将其应用于浏览器的方法:
protected override void OnRender(DrawingContext drawingContext)
{
base.OnRender(drawingContext);
var layer = AdornerLayer.GetAdornerLayer(browser);
layer.Add(new SillyAdorner(browser));
}
Run Code Online (Sandbox Code Playgroud)
有没有任何黑客或解决方法?
编辑:我正在使用.NET 4.0,如果这有所作为.
编辑#2:WebBrowser似乎继承自HwndHost,我已经看到了关于adorners和hwndsources的另外一两个问题,但我没有看到任何看起来像我可以为WebControl实现它的东西,但希望这是有用的信息有人.
我有一个ViewModel集合,它们使用样式呈现为制表符,以拉出要在选项卡上显示的相关内容:
public class TabViewModel : DependencyObject
{
public object Content
{
get { return (object)GetValue(ContentProperty); }
set
{
SetValue(ContentProperty, value);
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是TabControl:
<TabControl
ItemsSource={Binding MyCollectionOfTabViewModels}"
ItemContainerStyle="{StaticResource TabItemStyle}" />
Run Code Online (Sandbox Code Playgroud)
这是风格
<Style TargetType="TabItem" x:Key="TabItemStyle">
<Setter Property="Content" Value="{Binding Content}"/>
</Style>
Run Code Online (Sandbox Code Playgroud)
我们正在创建一个usercontrol实例,并将TabViewModel的"Content"属性设置为该属性,以便userItrol显示在TabItem的Content区域中.
MyCollectionOfViewModels.Add(new TabViewModel()
{
Content = new MyUserControl();
});
Run Code Online (Sandbox Code Playgroud)
我的问题是,我想允许添加到TabViewModel的Content属性的MyUserControl(或其任何子控件)引发TabViewModel处理的事件.
谁知道我会怎么做?
我们已经尝试过使用RoutedEvents和RoutedCommands,但是无法让任何东西100%工作并让它与MVVM兼容.我真的认为这可以通过RoutedEvent或RoutedCommand完成,但我似乎无法让它工作.
注意:我已经删除了一些相关的Prism特定代码,但是如果你想知道我们为什么做这么愚蠢的事情,那是因为我们试图通过使用Prism的RegionManager来保持控制不可知.
如何从ViewModel关闭View?
我有一个WPF窗口,它定义了多个Regions并用作Shell来托管我的应用程序的视图.我希望View能够从Region中删除自己,或者从标签容器中关闭它.如何从ViewModel完成此行为.
我有一个带有两个文本框的WPF视图.当用户像Tab一样击中键盘上的向下箭头时,我想自动将焦点从第一个文本框向前移动到第二个文本框.
似乎我应该能够100%声明地执行此操作,但出于某种原因,我认为这样做的命令似乎没有做任何事情.这是我的第一次尝试不起作用:
<StackPanel>
<TextBox Text="Test">
<TextBox.InputBindings>
<!-- I realize ComponentCommands.MoveFocusDown doesn't work...
This is just an example of what I've tried and the type
of answer I'm looking for -->
<KeyBinding Key="Down" Command="ComponentCommands.MoveFocusDown" />
</TextBox.InputBindings>
</TextBox>
<TextBox></TextBox>
</StackPanel>
Run Code Online (Sandbox Code Playgroud)
有人对这个有经验么?好像我应该能够使用InputBindings或EventTrigger来做到这一点.
我正在使用MVVM,这是一个View问题.我可以放弃一点代码隐藏(作为一个视图关注,这是合理的),但它只是感觉我错过了一些东西.