当用户第一次运行我的程序时,我希望他们通过一系列提示.每次他们点击某个"检查点"时,程序会暂停它的操作,背景会有点模糊(除了提示引用的窗口区域),并且提示将出现在顶部,解释如何使用它/做什么等
我不知道该怎么称呼它,在我脑海里它被称为"教程提示",但谷歌搜索任何与此相关的东西显示了大量的WPF/C#通用教程.
最好的方法是什么?我真的只是看着使用弹出窗口和控制它们何时可见?是否有更好/更优雅的解决方案或任何资源来帮助解决这个问题?
好吧,我想我可能已经投入了太多时间,但这听起来像是一个很酷的挑战:P
我创建了一个名为TipFocusDecorator处理所有这一切的Decorator类.
public class TipFocusDecorator : Decorator
{
public bool IsOpen
{
get { return (bool)GetValue(IsOpenProperty); }
set { SetValue(IsOpenProperty, value); }
}
// Using a DependencyProperty as the backing store for Open. This enables animation, styling, binding, etc...
public static readonly DependencyProperty IsOpenProperty =
DependencyProperty.Register("IsOpen", typeof(bool), typeof(TipFocusDecorator),
new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, IsOpenPropertyChanged));
public string TipText
{
get { return (string)GetValue(TipTextProperty); }
set { SetValue(TipTextProperty, value); }
}
// Using a DependencyProperty as the backing store for TipText. This enables animation, styling, binding, etc...
public static readonly DependencyProperty TipTextProperty =
DependencyProperty.Register("TipText", typeof(string), typeof(TipFocusDecorator), new UIPropertyMetadata(string.Empty));
public bool HasBeenShown
{
get { return (bool)GetValue(HasBeenShownProperty); }
set { SetValue(HasBeenShownProperty, value); }
}
// Using a DependencyProperty as the backing store for HasBeenShown. This enables animation, styling, binding, etc...
public static readonly DependencyProperty HasBeenShownProperty =
DependencyProperty.Register("HasBeenShown", typeof(bool), typeof(TipFocusDecorator), new UIPropertyMetadata(false));
private static void IsOpenPropertyChanged(object sender, DependencyPropertyChangedEventArgs e)
{
var decorator = sender as TipFocusDecorator;
if ((bool)e.NewValue)
{
if (!decorator.HasBeenShown)
decorator.HasBeenShown = true;
decorator.Open();
}
if (!(bool)e.NewValue)
{
decorator.Close();
}
}
TipFocusAdorner adorner;
protected void Open()
{
adorner = new TipFocusAdorner(this.Child);
var adornerLayer = AdornerLayer.GetAdornerLayer(this.Child);
adornerLayer.Add(adorner);
MessageBox.Show(TipText); // Change for your custom tip Window
IsOpen = false;
}
protected void Close()
{
var adornerLayer = AdornerLayer.GetAdornerLayer(this.Child);
adornerLayer.Remove(adorner);
adorner = null;
}
}
Run Code Online (Sandbox Code Playgroud)
必须在要关注的控件周围的XAML中使用此装饰器.它有三个属性:IsOpen,TipText和HasBeenShown.IsOpen必须设置为true使焦点和提示窗口出现(并false在提示窗口关闭时自动设置).TipText允许您定义必须在提示窗口中显示的文本.并HasBeenShown跟踪是否已显示提示窗口,因此它只显示一次.您可以对所有这些属性使用Bindings,也可以从代码隐藏中设置它们.
要创建焦点效应下,此类使用另一个自定义装饰器,在TipFocusAdorner:
public class TipFocusAdorner : Adorner
{
public TipFocusAdorner(UIElement adornedElement)
: base(adornedElement)
{
}
protected override void OnRender(System.Windows.Media.DrawingContext drawingContext)
{
base.OnRender(drawingContext);
var root = Window.GetWindow(this);
var adornerLayer = AdornerLayer.GetAdornerLayer(AdornedElement);
var presentationSource = PresentationSource.FromVisual(adornerLayer);
Matrix transformToDevice = presentationSource.CompositionTarget.TransformToDevice;
var sizeInPixels = transformToDevice.Transform((Vector)adornerLayer.RenderSize);
RenderTargetBitmap rtb = new RenderTargetBitmap((int)(sizeInPixels.X), (int)(sizeInPixels.Y), 96, 96, PixelFormats.Default);
var oldEffect = root.Effect;
var oldVisibility = AdornedElement.Visibility;
root.Effect = new BlurEffect();
AdornedElement.SetCurrentValue(FrameworkElement.VisibilityProperty, Visibility.Hidden);
rtb.Render(root);
AdornedElement.SetCurrentValue(FrameworkElement.VisibilityProperty, oldVisibility);
root.Effect = oldEffect;
drawingContext.DrawImage(rtb, adornerLayer.TransformToVisual(AdornedElement).TransformBounds(new Rect(adornerLayer.RenderSize)));
drawingContext.DrawRectangle(new SolidColorBrush(Color.FromArgb(22, 0, 0, 0)), null, adornerLayer.TransformToVisual(AdornedElement).TransformBounds(new Rect(adornerLayer.RenderSize)));
drawingContext.DrawRectangle(new VisualBrush(AdornedElement) { AlignmentX = AlignmentX.Left, TileMode = TileMode.None, Stretch = Stretch.None },
null,
AdornedElement.RenderTransform.TransformBounds(new Rect(AdornedElement.RenderSize)));
}
}
Run Code Online (Sandbox Code Playgroud)
这种模糊和模糊(并冻结,因为它实际上使用屏幕捕获)所有窗口,同时保持所需的控件聚焦和清晰(和移动 - 即在文本框中,文本输入插入符号仍将是可见和闪烁).
要使用此Decorator,您只需在XAML中将其设置为:
<StackPanel>
<local:TipFocusDecorator x:Name="LoginDecorator"
TipText="Enter your username and password and click 'Login'"
IsOpen="{Binding ShowLoginTip}">
<local:LoginForm />
</local:TipFocusDecorator>
</StackPanel>
Run Code Online (Sandbox Code Playgroud)
最后的结果,当ShowLoginTip设置为true:
已知的问题
现在,这使用一个简单的方法MessageBox来显示提示,但是您可以创建自己Window的提示类,根据需要设置样式,然后用ShowDialog()而不是调用它MessageBox.Show()(Window如果你想要它,你也可以控制它出现的位置)出现在焦点控件旁边或类似的东西).
此外,这将无法立即在UserControls内部工作,因为AdornerLayer.GetAdornerLayer(AdornedElement)将null在UserControls内返回.这可以通过查找(或父级的父级,递归)AdornerLayer的PARENT 来轻松修复UserControl.有这样的功能.
这对于Pages也不适用,仅适用于Windows.只是因为我Window.GetWindow(this)用来获取Window装饰器的父级...你可以使用其他函数来获取父级,这可以用于Windows,Pages或其他任何东西.与AdornerLayer问题一样,这里有很多解决方案.
此外,我猜这可能会以某种方式制作动画(例如,使模糊和暗淡效果逐渐显现),但还没有真正研究过它......
| 归档时间: |
|
| 查看次数: |
193 次 |
| 最近记录: |