- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我在 WPF 中创建了一个自定义控件“Toast Notification”,我想在 MVVM 中使用它来显示消息,但我不知道在哪里实现它(主窗口或每个页面)以及如何从每个页面发送消息到 toast通知。请帮我解决这个问题。
public class Toast:Control
{
static Toast()
{
DefaultStyleKeyProperty.OverrideMetadata (typeof (Toast),new FrameworkPropertyMetadata (typeof (Toast)));
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate ();
ChangeVisualState ();
}
public static readonly DependencyProperty TextProperty=
DependencyProperty.Register ("Text",typeof (string),typeof (Toast),new PropertyMetadata ("Sample Text"));
public static readonly DependencyProperty ToastIconProperty=
DependencyProperty.Register ("ToastIcon",typeof (ToastIconType),typeof (Toast),new PropertyMetadata (ToastIconType.None,OnToastIconChanged));
public static readonly DependencyProperty IsToastVisibleProperty=
DependencyProperty.Register ("IsToastVisible",typeof (bool),typeof (Toast),new PropertyMetadata (false,OnIsToastVisibleChanged));
public static readonly DependencyProperty DurationProperty=
DependencyProperty.Register ("Duration",typeof (TimeSpan),typeof (Toast),new PropertyMetadata (TimeSpan.FromSeconds (10),OnDurationChanged));
public static readonly DependencyProperty ImageGeometryProperty=
DependencyProperty.Register ("ImageGeometry",typeof (Geometry),typeof (Toast));
public string Text
{
get { return (string)GetValue (TextProperty); }
set { SetValue (TextProperty,value); }
}
public bool IsToastVisible
{
get { return (bool)GetValue (IsToastVisibleProperty); }
set { SetValue (IsToastVisibleProperty,value); ChangeVisualState (); }
}
public ToastIconType ToastIcon
{
get { return (ToastIconType)GetValue (ToastIconProperty); }
set { SetValue (ToastIconProperty,value); }
}
public TimeSpan Duration
{
get { return (TimeSpan)GetValue (DurationProperty); }
set { SetValue (DurationProperty,value); }
}
public Geometry ImageGeometry
{
get { return (Geometry)GetValue (ImageGeometryProperty); }
set { SetValue (ImageGeometryProperty,value); }
}
private static void OnDurationChanged(DependencyObject d,DependencyPropertyChangedEventArgs e)
{
var control=(Toast)d;
var value=(TimeSpan)e.NewValue;
control.Duration=value;
}
private static void OnIsToastVisibleChanged(DependencyObject d,DependencyPropertyChangedEventArgs e)
{
var c=(Toast)d;
var value=(bool)e.NewValue;
c.IsToastVisible=value;
}
private void ChangeVisualState()
{
if (IsToastVisible)
{
DoubleAnimation da=new DoubleAnimation { From=1,To=0,Duration=TimeSpan.FromSeconds (Duration.Seconds) };
CubicEase cubicEase=new CubicEase ();
cubicEase.EasingMode=EasingMode.EaseInOut;
da.EasingFunction=cubicEase;
da.Completed+=(sender,e) => IsToastVisible=false;
BeginAnimation (OpacityProperty,da);
}
else
{
Opacity=0;
}
}
private static void OnToastIconChanged(DependencyObject d,DependencyPropertyChangedEventArgs e)
{
var control=(Toast)d;
var value=(ToastIconType)e.NewValue;
switch (value)
{
case ToastIconType.Information:
control.ImageGeometry=Geometry.Parse ("M3.6069946,1.8659973C2.6459963,1.8659973,1.8660278,2.6480103,1.8660278,3.6080017L1.8660278,20.546021C1.8660278,21.507019,2.6459963,22.288025,3.6069946,22.288025L11.647035,22.288025 9.6170056,27.481018 18.038026,22.288025 28.124027,22.288025C29.085025,22.288025,29.865054,21.507019,29.865054,20.546021L29.865054,3.6080017C29.865054,2.6480103,29.085025,1.8659973,28.124027,1.8659973z M3.6069946,0L28.124027,0C30.11304,0,31.731998,1.6190186,31.731998,3.6080017L31.731998,20.546021C31.731998,22.536011,30.11304,24.154022,28.124027,24.154022L18.567018,24.154022 5.8439948,32 8.9130261,24.154022 3.6069946,24.154022C1.618042,24.154022,-2.120687E-07,22.536011,0,20.546021L0,3.6080017C-2.120687E-07,1.6190186,1.618042,0,3.6069946,0z");
break;
case ToastIconType.Warning:
control.ImageGeometry=Geometry.Parse ("M13.950004,24.5L13.950004,28.299988 17.950004,28.299988 17.950004,24.5z M13.950004,10.399963L13.950004,21.699951 17.950004,21.699951 17.950004,10.399963z M15.950004,0C16.349998,0,16.750007,0.19995117,16.950004,0.69995117L31.750011,30.099976C31.949993,30.5 31.949993,31 31.750011,31.399963 31.549999,31.799988 31.150005,32 30.750011,32L1.1499981,32C0.75000406,32 0.34999478,31.799988 0.14999761,31.399963 -0.049999204,31 -0.049999204,30.5 0.14999761,30.099976L14.950004,0.69995117C15.150001,0.19995117,15.549995,0,15.950004,0z");
break;
}
}
public enum ToastIconType
{
None=0,
Information=1,
Warning=2
}
}
还有我的 toast 风格:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MetroCustomControls">
<Style TargetType="{x:Type local:Toast}">
<Style.Resources>
<SolidColorBrush x:Key="Toast.Static.Background" Color="LightGray" />
<SolidColorBrush x:Key="Toast.Static.BorderBrush" Color="Gray" />
<SolidColorBrush x:Key="Toast.Static.Foreground" Color="DimGray" />
</Style.Resources>
<Setter Property="Background" Value="{StaticResource Toast.Static.Background}" />
<Setter Property="BorderBrush" Value="{StaticResource Toast.Static.BorderBrush}" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="Foreground" Value="{StaticResource Toast.Static.Foreground}" />
<Setter Property="FontFamily" Value="Segoe UI Light" />
<Setter Property="FontSize" Value="14" />
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="HorizontalContentAlignment" Value="Center" />
<Setter Property="VerticalAlignment" Value="Bottom" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="Margin" Value="0,0,0,10" />
<Setter Property="Focusable" Value="False" />
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:Toast}">
<Grid x:Name="template_Root">
<Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="2" HorizontalAlignment="{TemplateBinding HorizontalAlignment}" VerticalAlignment="{TemplateBinding VerticalAlignment}" Margin="0,0,0,20">
<StackPanel Orientation="Horizontal">
<Path x:Name="path" Margin="6,0,0,0" Fill="{TemplateBinding Foreground}" Stretch="Uniform" Width="12" Height="12" Data="{TemplateBinding ImageGeometry}" />
<TextBlock Text="{TemplateBinding Text}" Foreground="{TemplateBinding Foreground}" FontSize="{TemplateBinding FontSize}" FontFamily="{TemplateBinding FontFamily}" Padding="5" />
</StackPanel>
</Border>
</Grid>
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding ToastIcon,RelativeSource={RelativeSource Self}}" Value="None">
<Setter TargetName="path" Property="Visibility" Value="Collapsed" />
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
最佳答案
这类似于MVVM中Dialogs的问题。
理想的解决方案是将功能包装在 DialogService
中,或者在您的情况下是 ToastService
,您可以将其注入(inject)到需要它的 ViewModel 中。
因此您的 MainWindow 或根 ViewModel 具有显示 Toast 的控制权和能力。然后你有一个看起来像这样的 IToastService
:
public class ToastService
{
public event Action<String> ToastMessageRecieved;
public void ShowToast(string message)
{
ToastMessageRecieved(message);
}
}
ShowToast
操作(实际显示 toast 的东西)的使用者,比如 RootViewModel,可以订阅 ToastMessageRecieved
操作:
public MyRootViewModel(ToastService toastService)
{
//keep it as a dependency in case we want to show toasts
this.toastService = toastService;
toastService.ToastMessageRecieved += (message) =>
{
//here's where you actually show your toast, however that's done
//MyRootViewModel has the actual UI element reference. It only
//appears in this one place.
Toast.Message = message;
};
}
然后任何其他想要显示 Toast 的 ViewModel 使用该服务:
public MyRandomToastGeneratingViewModel(ToastService toastService)
{
//our service is inejcted as a dependency
this.toastService = toastService;
}
public void ShowAToastButtonPressed()
{
toastService.ShowToast("My great toast!");
}
理想情况下,您可以使用某种依赖注入(inject)框架 - 但对于此类事情值得实现。对话服务,诸如 toast 、工厂和数据访问之类的东西非常适合 MVVM 和 DI。
要让实际控件(您拥有的单个实例)位于其他所有内容之上,在 Window 或 RootView 中,您可以简单地让它占据与普通内容相同的网格单元格。这就是我通常做重叠控制的方式:
<Window x:Class="MyApp.MainWindow"
...>
<Grid>
//my normal content
<myControls:Toast VerticalAlignment="Bottom" HorizontalAlignment="Center" Margin="20"/>
</Grid>
</Window>
它们将按照您添加它们的顺序占用相同的空间。
关于c# - 在 WPF MVVM 中使用 Toast 通知,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41537173/
我已经对这个主题进行了一些研究,并且已经在少数应用程序中使用了 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
我是一名优秀的程序员,十分优秀!