关于在MVVM架构下WPF中UserControl的 visibility Binding问题。 UserControl MVVM
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于在MVVM架构下WPF中UserControl的 visibility Binding问题。 UserControl MVVM相关的知识,希望对你有一定的参考价值。
我在ViewModel中用一个枚举来定义页面状态,根据状态控制界面中的UserControl的显隐:
ViewModel:
类似的还有其他三个属性ChatEnabled、UserInfoEnabled、GroupMebEnabled,我通过控制MainState来控制界面UserControl的显隐:
之前我也是这样做的,不过控制的是普通界面元素的显隐(如Button,Textbook等),但是我发现同样的方法用在UserControl上就不管用了(结果是全部显示)。我在DeBug下看过XAML中的变量:
为什么没有效果呢?
usercontrol如果不指定绑定,默认的是uc中的VM,需要指定要绑定的page的vm。
如:
<mycontrols:TimePicker VerticalAlignment="Center" Visibility="Binding DataContext.IsShowTimeUI,Converter=StaticResource BoolToVisibilityCollapseConverter,RelativeSource=RelativeSource FindAncestor,AncestorType=x:Type Page" Width="100" Height="30"></mycontrols:TimePicker>这句代码表示绑定到父page的datacontext上。如果直接写,Binding IsShowTimeUI,肯定是不起作用的。
外面包一个层<Grid Visibility=Binding ChatEnabled>这里放用户控件</Grid>
你可以用转换器,设置一个变量,多个状态,根据不同状态选择显示不同界面。
比如 变量1A,B,C
public class AccountStatusToVisibility : IValueConverter#region "IValueConverter Members"
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
if (value == null)
return Visibility.Collapsed;
if (parameter != null)
var p = parameter.ToString();
if (p.Contains(","))
return p.Split(',').Contains(value.ToString(), StringComparer.OrdinalIgnoreCase) ? Visibility.Visible : Visibility.Collapsed;
return string.Equals(p, value.ToString(), StringComparison.OrdinalIgnoreCase) ? Visibility.Visible : Visibility.Collapsed;
return Visibility.Collapsed;
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
throw new NotImplementedException();
#endregion
<Grid Visibility="Binding Path=变量1,Converter=StaticResource ToVisibility,ConverterParameter='A'"</Grid>
MVVM 架构 WPF
【中文标题】MVVM 架构 WPF【英文标题】:MVVM architecture WPF 【发布时间】:2016-06-29 04:39:48 【问题描述】:我对 WPF 中的 MVVM
有一点架构问题。我有View
,其中包含编写一些代码或使用computers camera.
If user choose to not scan the code, I can bind
Command 扫描QRCode
的选项,没有问题。
用户选择扫描二维码时出现问题。
当用户按下扫描代码时,屏幕的一部分被折叠并且相机显示在屏幕上。我必须在 View
后面的代码中执行此操作,所以我在 View
中得到的代码在 MVVM 中不好。
View 的代码如下所示:
private void Scan_Click(object sender, RoutedEventArgs e)
if (_finalVideo.IsRunning)
_finalVideo.Stop();
_finalVideo = new VideoCaptureDevice(_cameraDevices[CamerasList.SelectedIndex].MonikerString);
_finalVideo.NewFrame += (s, a) =>
try
System.Drawing.Image img = (Bitmap)a.Frame.Clone();
var ms = new MemoryStream();
img.Save(ms, ImageFormat.Bmp);
ms.Seek(0, SeekOrigin.Begin);
var bitmapImage = new BitmapImage();
bitmapImage.BeginInit();
bitmapImage.StreamSource = ms;
bitmapImage.EndInit();
bitmapImage.Freeze();
Dispatcher.BeginInvoke(new ThreadStart(() =>
CameraStream.Source = bitmapImage;
ReadQrCode(bitmapImage);
));
catch
//exc
;
_finalVideo.Start();
我如何用MVVM
解决这个问题?
【问题讨论】:
是什么让您认为在视图中隐藏代码是不好的?如果它正在做与 UI 相关的工作,那么拥有这样的代码是完全可以的——这就是你正在做的事情。 我通常只是编写一个接口来抽象这些外部输入/输出的东西。因此,您最终会得到一个ICommand Scan
属性,该属性在执行时会在接口上调用 Task<QrCode> ReadQrCodeFromCameraAsync
方法。在你的单元测试中,你做了这个接口的假实现。
【参考方案1】:
这很简单,只要您掌握了它并知道“用户控件”和视图之间的区别。
第一个声明是,理想情况下,后面的代码对于视图应该是空的。这是真实的。
但是,这不适用于用户控件。用户控件可以并且应该有代码,因为它们需要自我维持并且不将其逻辑提取到某些视图模型类中。
那么用户控件和视图之间有什么区别?是的,它们通常都派生自UserControl
,但这不会使视图默认成为用户控件。重要的是,视图是为一个应用程序制作的非常特定的 UI 片段,不太可能在其他应用程序中重用。
例如,应用程序 A 中的 CustomerDetailView
或 CustomerDetailPage
将不同于应用程序 B 的同一视图,因为应用程序 B 可能对 CustomerDetailView
有不同的要求。
另一端的用户控件可以跨应用程序重复使用,例如DatePicker
、CalendarControl
或CameraControl
。例如,此控件可用于可能需要相机的多个应用程序中。
这里重要的是,“用户控件”不知道您的应用程序结构,因此没有视图模型、业务/域模型等。如果您想允许 ViewModels 绑定到您的用户控件(ICommand
for例如,启动和回调,或将生成的图片绑定到 ViewModel),然后将依赖项属性放入用户控件中。
当您在应用程序中使用此用户控件时,您只需将视图模型绑定到这些依赖属性 (DP),然后您就获得了抽象。
TL;DR: 视图中的代码不好,用户控件中的代码必要。
【讨论】:
视图中的代码是完全可以的,只要它与演示相关。您对 Control 与 View 的区别很有用,但不要将其固定到特定的类。以上是关于关于在MVVM架构下WPF中UserControl的 visibility Binding问题。 UserControl MVVM的主要内容,如果未能解决你的问题,请参考以下文章
如何在 MVVM 中的 UserControl 之间进行通信 - WPF 应用程序
在 UserControl WPF MVVM caliburn 内的 UserControl 之间切换
使用 MVVM 在 MainWindow 上绑定 UserControl 视图模型