<Grid>
<Image x:Name="BackgroundImage" Source="/Assets/background.png" />
<Rectangle x:Name="ClippingRect" Margin="50" Fill="#30f0" />
</Grid>
How do I apply alpha mask, or clipping mask, so everything except the rectangle will be blurred?
I do the usual: GraphicsEffect->EffectFactory->Brush->Set to SpriteVisual
var graphicsEffect = new BlendEffect
{
Mode = BlendEffectMode.Multiply,
Background = new ColorSourceEffect
{
Name = "Tint",
Color = Windows.UI.Color.FromArgb(50,0,255,0),
},
Foreground = new GaussianBlurEffect()
{
Name = "Blur",
Source = new CompositionEffectSourceParameter("Backdrop"),
BlurAmount = (float)20,
BorderMode = EffectBorderMode.Hard,
}
};
var blurEffectFactory = _compositor.CreateEffectFactory(graphicsEffect,
new[] { "Blur.BlurAmount", "Tint.Color" });
var _brush = blurEffectFactory.CreateBrush();
_brush.SetSourceParameter("Backdrop", _compositor.CreateBackdropBrush());
var blurSprite = _compositor.CreateSpriteVisual();
blurSprite.Size = new Vector2((float)BackgroundImage.ActualWidth, (float)BackgroundImage.ActualHeight);
blurSprite.Brush = _brush;
ElementCompositionPreview.SetElementChildVisual(BackgroundImage, blurSprite);
You can use the following solution which is using twice the same image.
I'm using one for the blurred background and one for the clipped foreground.
The idea is to draw the background blurred full-size and over it only the clipped region you want using the Clip property for the foreground visual.
The XAML for the page/control:
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Image x:Name="BackgroundImage" Source="/Assets/Purple Tentacle.png" />
<Image x:Name="ClippedImage" Source="/Assets/Purple Tentacle.png" />
</Grid>
The code behind:
protected override void OnNavigatedTo(NavigationEventArgs e)
{
_compositor = ElementCompositionPreview.GetElementVisual(this).Compositor;
_backgroundImageVisual = ElementCompositionPreview.GetElementVisual(BackgroundImage);
var graphicEffect = new BlendEffect
{
Mode = BlendEffectMode.Multiply,
Background = new ColorSourceEffect
{
Color= Color.FromArgb(50, 0, 255, 0)
},
Foreground = new GaussianBlurEffect
{
Source = new CompositionEffectSourceParameter("Backdrop"),
BlurAmount = 20.0f,
BorderMode = EffectBorderMode.Hard
}
};
var backdropBrush = _compositor.CreateBackdropBrush();
var blurEffectFactory = _compositor.CreateEffectFactory(graphicEffect);
_brush = blurEffectFactory.CreateBrush();
_brush.SetSourceParameter("Backdrop", backdropBrush);
_blurSprite = _compositor.CreateSpriteVisual();
_blurSprite.Brush = _brush;
ElementCompositionPreview.SetElementChildVisual(BackgroundImage, _blurSprite);
_foregroundImageVisual = ElementCompositionPreview.GetElementVisual(ClippedImage);
_foregroundImageVisual.Clip = _compositor.CreateInsetClip(100, 100, 100, 100);
SizeChanged += MainPage_SizeChanged;
MainPage_SizeChanged(this, null);
}
private void MainPage_SizeChanged(object sender, SizeChangedEventArgs e)
{
_blurSprite.Size = new Vector2((float) BackgroundImage.ActualWidth, (float) BackgroundImage.ActualHeight);
// change the clip values here to change the non-blurred region
_foregroundImageVisual.Clip = _compositor.CreateInsetClip(100, 100, 100, 100);
}
In Creators update, I can create class derived from XamlCompositionBrushBase and the apply it to the xaml element, so it does the blurring:
<Grid>
<Image x:Name="BackgroundImage" Source="/Assets/background.png" />
<Path>
<Path.Fill>
<local:BlurTintBrush BlurRadius="5" TintColor="Black" TintOpacity="0.7" />
</Path.Fill>
<Path.Data>
<GeometryGroup>
<RectangleGeometry x:Name="ImageGeometry" Rect="0,0,1027,768" /
<RectangleGeometry x:Name="CropGeometry" Rect="50,50,25,25" />
</GeometryGroup>
</Path.Data>
</Path>
</Grid>
Related
I need to implement this drop-down menu in WPF:
When you click on the number of the question, it should open additional content. I can't attach the code, because there is not even an approximate implementation. I tried to implement via Grid.Row and Grid.Column, ListBox, StackPanel but I just didn't have enough knowledge.
Here is the code I've tried:
<Grid>
<ListBox HorizontalContentAlignment="Left">
<Button Content="1"/>
<TextBlock Text="Content"/>
<Button Content="2"/>
</ListBox>
</Grid>
Step 1: Add a User Control to your project.
Step 2: Name it Arrow.
Step 3: This Control will act as a drop-down arrow for us. Add the following XAML code to the control:
<UserControl x:Class="Question_Builder_App.Controls.Arrow"
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:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d">
<Grid>
<Border BorderThickness="0,0,5,0" Height="15" BorderBrush="Black" RenderTransformOrigin="0.5,0.5" Width="10" Margin="0,0,0,10">
<Border.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform Angle="135"/>
<TranslateTransform/>
</TransformGroup>
</Border.RenderTransform>
</Border>
<Border BorderThickness="0,0,5,0" BorderBrush="Black" RenderTransformOrigin="0.5,0.5" Height="15" Width="10" Margin="0,11,0,0" Grid.RowSpan="2">
<Border.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform Angle="225"/>
<TranslateTransform/>
</TransformGroup>
</Border.RenderTransform>
</Border>
</Grid>
The control should look like this:
Step 4: Add the following XAML to your MainWindow:
<Window x:Class="Question_Builder_App.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800" Background="#FF283246">
<Grid x:Name="MainGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<StackPanel x:Name="LeftPanel" Grid.Column="0">
<Border CornerRadius="10,10,10,10" HorizontalAlignment="Center" VerticalAlignment="Center" Background="#FF033B50" Margin="50,20,50,0">
<Button x:Name="AddQuestion_BTN" FontSize="24" Content="+" HorizontalAlignment="Stretch" VerticalAlignment="Center" Foreground="White" HorizontalContentAlignment="Left" Padding="10,0,10,0" Click="AddQuestion_BTN_Click" Background="{x:Null}" BorderBrush="{x:Null}"/>
</Border>
</StackPanel>
<Frame x:Name="RightPanel" Grid.Column="1" NavigationUIVisibility="Hidden"/>
</Grid>
The designer should look like this:
Step 5: Now lets add some C# codes to our MainWindow:
using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace Question_Builder_App
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
AddSampleData("Test Button 1", "Test Button");
AddSampleData("Test Button 2", "Test Button");
AddSampleData("Test Button 3", "Test Button");
}
private int ButtonCount = 0;
private ObservableCollection<DataModel> PageCollection = new ObservableCollection<DataModel>();
private class DataModel
{
public string MainButtonName { get; set; }
public string PageName { get; set; }
public Page DisplayPage { get; set; }
}
private static string CreateInputWindow(string WindowDescription)
{
Window ButtonInfoWindow = new Window();
ButtonInfoWindow.Background = null; ButtonInfoWindow.SizeToContent = SizeToContent.WidthAndHeight;
StackPanel SP = new StackPanel();
Border TextDescription = AddBorder(WindowDescription, 24);
TextBox TB = new TextBox();
TB.MinWidth = 100; TB.FontSize = 24;
Button B = new Button();
B.FontSize = 24; B.Margin = new Thickness(0, 10, 0, 0); B.Content = "Set";
B.Click += delegate { ButtonInfoWindow.Close(); };
SP.Children.Add(TextDescription); SP.Children.Add(TB); SP.Children.Add(B);
ButtonInfoWindow.Content = SP;
ButtonInfoWindow.ShowDialog();
return TB.Text;
}
private void AddQuestion_BTN_Click(object sender, RoutedEventArgs e)
{
Border TopBorder = new Border();
TopBorder.CornerRadius = new CornerRadius(10); TopBorder.Background = new SolidColorBrush(Color.FromRgb(3, 59, 80)); TopBorder.HorizontalAlignment = HorizontalAlignment.Left;
TopBorder.Margin = new Thickness(40, 20, 40, 0);
StackPanel TopSPPanel = new StackPanel();
TopBorder.Child = TopSPPanel;
StackPanel LowerPanel = new StackPanel();
LowerPanel.Visibility = Visibility.Collapsed;
string MainButtonName = CreateInputWindow("What is the name of the button you wish to create?");
Border NewQuestion_BTN = AddBorder(ButtonCount + 1 + ". " + MainButtonName, 24);
NewQuestion_BTN.MouseLeftButtonDown += delegate
{
if (LowerPanel.Visibility == Visibility.Visible)
{
LowerPanel.Visibility = Visibility.Collapsed;
NewQuestion_BTN.Background = new SolidColorBrush(Color.FromRgb(3, 59, 80));
}
else
{
LowerPanel.Visibility = Visibility.Visible;
NewQuestion_BTN.Background = new SolidColorBrush(Colors.Blue);
}
};
TopSPPanel.Children.Add(NewQuestion_BTN);
LowerPanel.Margin = new Thickness(0, 10, 0, 10);
Border LowerNewQuestion_BTN = AddBorder("+", 24);
LowerNewQuestion_BTN.MouseLeftButtonDown += delegate
{
string InputText = CreateInputWindow("What is the name of the button you wish to create?");
Border ChooseQuestionBTN = AddBorder(LowerPanel.Children.Count + ". " + InputText, 16);
ChooseQuestionBTN.MouseLeftButtonDown += delegate
{
UncheckAllButtons();
ChooseQuestionBTN.Background = new SolidColorBrush(Colors.Aquamarine);
NavigateToPage(MainButtonName, InputText);
};
LowerPanel.Children.Insert(LowerPanel.Children.Count - 1, ChooseQuestionBTN);
};
LowerPanel.Children.Add(LowerNewQuestion_BTN); TopSPPanel.Children.Add(LowerPanel);
LeftPanel.Children.Insert(ButtonCount, TopBorder);
ButtonCount++;
}
private void NavigateToPage(string MainButtonText, string NameChecker)
{
bool CheckIfToADDANewPage = true;
foreach (DataModel PageFinder in PageCollection)
{
if (PageFinder.PageName == NameChecker && PageFinder.MainButtonName == MainButtonText)
{
RightPanel.Navigate(PageFinder.DisplayPage);
CheckIfToADDANewPage = false;
}
}
if (CheckIfToADDANewPage == true)
{
DataModel SavePage = new DataModel();
SavePage.MainButtonName = MainButtonText; SavePage.PageName = NameChecker; SavePage.DisplayPage = CreateANewPage();
PageCollection.Add(SavePage);
RightPanel.Navigate(SavePage.DisplayPage);
}
}
private static Page CreateANewPage()
{
Page QuestionPage = new Page();
StackPanel QuestionPanel = new StackPanel();
Border QuestionBorder = AddBorder("+", 24);
QuestionBorder.Margin = new Thickness(5, 20, 0, 0); QuestionBorder.Background = new SolidColorBrush(Colors.Aqua);
QuestionBorder.MouseLeftButtonDown += delegate
{
StackPanel UpperQuestionPanel = new StackPanel(); UpperQuestionPanel.Orientation = Orientation.Horizontal;
UpperQuestionPanel.Margin = new Thickness(0, 20, 0, 0);
Border QuestionNumberTXT = AddBorder(QuestionPanel.Children.Count.ToString(), 24);
QuestionNumberTXT.VerticalAlignment = VerticalAlignment.Top; QuestionNumberTXT.Background = new SolidColorBrush(Colors.Aqua);
Controls.Arrow PanelArrow = new Controls.Arrow();
PanelArrow.Margin = new Thickness(20, 10, 10, 0); PanelArrow.VerticalAlignment = VerticalAlignment.Top;
StackPanel InnerQuestionPanel = new StackPanel(); InnerQuestionPanel.Visibility = Visibility.Collapsed; InnerQuestionPanel.Margin = new Thickness(0, 10, 10, 0);
PanelArrow.MouseLeftButtonDown += delegate
{
if (InnerQuestionPanel.Visibility == Visibility.Collapsed)
{
InnerQuestionPanel.Visibility = Visibility.Visible;
PanelArrow.RenderTransform = new RotateTransform(90);
PanelArrow.Margin = new Thickness(45, 20, 10, 0);
if (InnerQuestionPanel.ActualWidth < 1)
{
Border InnerQuestionBorder = AddBorder(CreateInputWindow("Please enter description of the question: "), 24);
InnerQuestionBorder.MaxWidth = 800;
InnerQuestionPanel.Children.Insert(0, InnerQuestionBorder);
}
}
else
{
InnerQuestionPanel.Visibility = Visibility.Collapsed;
PanelArrow.RenderTransform = new RotateTransform(0);
PanelArrow.Margin = new Thickness(20, 10, 10, 0);
}
};
WrapPanel NewQuestionWrapPanel = new WrapPanel();
NewQuestionWrapPanel.Orientation = Orientation.Horizontal;
Border AddNewQuestionBTN = AddBorder("+", 24);
AddNewQuestionBTN.Margin = new Thickness(10, 10, 0, 0);
AddNewQuestionBTN.MouseLeftButtonDown += delegate
{
NewQuestionWrapPanel.MaxWidth = InnerQuestionPanel.ActualWidth;
Border ChooseNewQuestion = AddBorder(CreateInputWindow("Add new question: "), 24);
ChooseNewQuestion.Margin = new Thickness(10, 10, 0, 0);
NewQuestionWrapPanel.Children.Insert(NewQuestionWrapPanel.Children.Count - 1, ChooseNewQuestion);
};
NewQuestionWrapPanel.Children.Insert(NewQuestionWrapPanel.Children.Count, AddNewQuestionBTN); InnerQuestionPanel.Children.Add(NewQuestionWrapPanel);
UpperQuestionPanel.Children.Add(QuestionNumberTXT); UpperQuestionPanel.Children.Add(PanelArrow); UpperQuestionPanel.Children.Add(InnerQuestionPanel);
QuestionPanel.Children.Insert(QuestionPanel.Children.Count - 1, UpperQuestionPanel);
};
QuestionPanel.Children.Insert(QuestionPanel.Children.Count, QuestionBorder); QuestionPage.Content = QuestionPanel;
return QuestionPage;
}
private static Border AddBorder(string InnerText, int SetFontSize)
{
Border NewBorder = new Border();
NewBorder.CornerRadius = new CornerRadius(10); NewBorder.Background = new SolidColorBrush(Color.FromRgb(3, 59, 80)); NewBorder.HorizontalAlignment = HorizontalAlignment.Left;
NewBorder.Margin = new Thickness(10, 0, 10, 0);
TextBlock NewButton = new TextBlock();
NewButton.FontSize = SetFontSize; NewButton.VerticalAlignment = VerticalAlignment.Stretch; NewButton.Foreground = new SolidColorBrush(Colors.White);
NewButton.Margin = new Thickness(10, 0, 10, 0);
NewButton.Text = InnerText;
NewButton.TextWrapping = TextWrapping.Wrap;
NewBorder.Child = NewButton;
return NewBorder;
}
private void AddSampleData(string MainButtonText, string SecondaryButtonText)
{
Border TopBorder = new Border();
TopBorder.CornerRadius = new CornerRadius(10); TopBorder.Background = new SolidColorBrush(Color.FromRgb(3, 59, 80)); TopBorder.HorizontalAlignment = HorizontalAlignment.Left;
TopBorder.Margin = new Thickness(40, 20, 40, 0);
StackPanel TopSPPanel = new StackPanel();
TopBorder.Child = TopSPPanel;
StackPanel LowerPanel = new StackPanel();
LowerPanel.Visibility = Visibility.Collapsed;
Border NewQuestion_BTN = AddBorder(ButtonCount + 1 + ". " + MainButtonText, 24);
NewQuestion_BTN.MouseLeftButtonDown += delegate
{
if (LowerPanel.Visibility == Visibility.Visible)
{
LowerPanel.Visibility = Visibility.Collapsed;
NewQuestion_BTN.Background = new SolidColorBrush(Color.FromRgb(3, 59, 80));
}
else
{
LowerPanel.Visibility = Visibility.Visible;
NewQuestion_BTN.Background = new SolidColorBrush(Colors.Blue);
}
};
TopSPPanel.Children.Add(NewQuestion_BTN);
LowerPanel.Margin = new Thickness(0, 10, 0, 10);
Border LowerNewQuestion_BTN = AddBorder("+", 24);
LowerNewQuestion_BTN.MouseLeftButtonDown += delegate
{
string InputText = CreateInputWindow("What is the name of the button you wish to create?");
Border ChooseQuestionBTN = AddBorder(LowerPanel.Children.Count + ". " + InputText, 16);
ChooseQuestionBTN.MouseLeftButtonDown += delegate
{
UncheckAllButtons();
ChooseQuestionBTN.Background = new SolidColorBrush(Colors.Aquamarine);
NavigateToPage(MainButtonText, InputText);
};
LowerPanel.Children.Insert(LowerPanel.Children.Count - 1, ChooseQuestionBTN);
};
Border SampleQuestionBTN = AddBorder(LowerPanel.Children.Count + 1 + ". " + SecondaryButtonText, 16);
SampleQuestionBTN.MouseLeftButtonDown += delegate
{
UncheckAllButtons();
SampleQuestionBTN.Background = new SolidColorBrush(Colors.Aquamarine);
NavigateToPage(MainButtonText, SecondaryButtonText);
};
LowerPanel.Children.Insert(LowerPanel.Children.Count, SampleQuestionBTN);
LowerPanel.Children.Add(LowerNewQuestion_BTN); TopSPPanel.Children.Add(LowerPanel);
LeftPanel.Children.Insert(ButtonCount, TopBorder);
ButtonCount++;
}
private void UncheckAllButtons()
{
foreach (Border _BR in LeftPanel.Children)
{
if (_BR.Child is StackPanel)
{
StackPanel SP = (StackPanel)_BR.Child;
foreach (UIElement UE in SP.Children)
{
if (UE is StackPanel)
{
StackPanel SP1 = (StackPanel)UE;
foreach (Border B in SP1.Children)
{
B.Background = null;
}
}
}
}
}
}
}
}
I'm trying to develop a WPF custom control that can be used to overlay other controls, effectively dimming them out so as to make it clear that they are not usable. This is similar to the effect you see on many web sites, where they grey out the background page when a pop-up is shown.
Trouble is, when it runs, instead of showing the contained controls dimly, they just disappear. I'll show the code below, along with a very simple sample usage.
Here is the code for control itself (namespace and usings omitted to save a bit of space)...
public class OverlayDisableControl : UserControl {
protected override void OnInitialized(EventArgs e) {
base.OnInitialized(e);
VerticalAlignment = VerticalAlignment.Stretch;
HorizontalAlignment = HorizontalAlignment.Stretch;
Grid grid = new Grid();
ContentPresenter content = new ContentPresenter {
Name = "content",
Content = Content
};
grid.Children.Add(content);
Grid overlay = new Grid {
Name = "Overlay",
Visibility = Visibility.Collapsed
};
Border background = new Border {
Name = "background",
VerticalAlignment = VerticalAlignment.Stretch,
HorizontalAlignment = HorizontalAlignment.Stretch,
Background = new SolidColorBrush(Colors.LightGray),
Opacity = .6
};
overlay.Children.Add(background);
grid.Children.Add(overlay);
Content = grid;
}
public static readonly DependencyProperty OverlayVisibleProperty =
DependencyProperty.Register("OverlayVisible", typeof(bool),
typeof(OverlayDisableControl),
new FrameworkPropertyMetadata(SetOverlayVisibleStatic));
public bool OverlayVisible {
get {
return (bool) GetValue(OverlayVisibleProperty);
}
set {
SetValue(OverlayVisibleProperty, value);
}
}
private static void SetOverlayVisibleStatic(DependencyObject d, DependencyPropertyChangedEventArgs e) {
(d as OverlayDisableControl).SetOverlayVisible(d as OverlayDisableControl, (bool) e.NewValue);
}
private void SetOverlayVisible(OverlayDisableControl odc, bool visible) {
if (visible) {
DoubleAnimation anim = new DoubleAnimation {
From = 0,
To = 1, // Visible
Duration = new Duration(TimeSpan.FromMilliseconds(350)),
EasingFunction = new QuadraticEase {
EasingMode = EasingMode.EaseInOut
}
};
odc.Visibility = Visibility.Visible;
odc.BeginAnimation(OpacityProperty, anim);
} else {
DoubleAnimation anim = new DoubleAnimation {
From = 1,
To = 0, // Invisible
Duration = new Duration(TimeSpan.FromMilliseconds(350)),
EasingFunction = new QuadraticEase {
EasingMode = EasingMode.EaseInOut
}
};
anim.Completed += (s1, e1) => {
odc.Visibility = Visibility.Collapsed;
};
odc.BeginAnimation(OpacityProperty, anim);
}
}
}
...and here is a sample usage. This is all you need, no code-behind, just drop this onto a window. The controls inside the GroupBox are just there for tesing...
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal">
<CheckBox Content="Show?"
Margin="3"
Name="ShowChk"
IsChecked="True" />
</StackPanel>
<local:OverlayDisableControl OverlayVisible="{Binding ElementName=ShowChk, Path=IsChecked, Mode=TwoWay}"
Grid.Row="1">
<GroupBox Header="Gratuitous controls"
Margin="3">
<StackPanel Orientation="Vertical">
<TextBlock Text="This is some text"
Margin="3" />
<TextBox Margin="3" />
<Button Content="Save"
Margin="3" />
</StackPanel>
</GroupBox>
</local:OverlayDisableControl>
</Grid>
Anyone any idea what I've done wrong?
You're animating / changing visibility of the UserControl itself, while it's the Grid overlay you're after.
Changes to your code:
public class OverlayDisableControl : UserControl
{
private Grid overlay = new Grid
{
Name = "Overlay",
Visibility = Visibility.Collapsed
};
protected override void OnInitialized(EventArgs e)
{
base.OnInitialized(e);
...
//Grid overlay = new Grid
//{
// Name = "Overlay",
// Visibility = Visibility.Collapsed
//};
...
}
...
private static void SetOverlayVisibleStatic(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
(d as OverlayDisableControl).SetOverlayVisible((bool)e.NewValue);
}
private void SetOverlayVisible(bool visible)
{
if (visible)
{
DoubleAnimation anim = new DoubleAnimation
{
...
};
overlay.Visibility = Visibility.Visible;
overlay.BeginAnimation(OpacityProperty, anim);
}
else
{
DoubleAnimation anim = new DoubleAnimation
{
...
};
anim.Completed += (s1, e1) => {
overlay.Visibility = Visibility.Collapsed;
};
overlay.BeginAnimation(OpacityProperty, anim);
}
}
}
I want to bind data to a grid in xaml. This is the code I am using for binding it:
<Grid x:Name="Example" Grid.Column="1" Grid.Row="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" >
<ContentPresenter Content="{Binding ExampleImage}" />
</Grid>
Now when I bind it using fixed width and height it will display the grid at set dimensions.
Code:
private Grid _exampleImage;
public Grid ExampleImage
{
get
{
if (SelectedSectie != null)
{
var convertFromString = System.Windows.Media.ColorConverter.ConvertFromString("#CCCCCC");
if (convertFromString != null)
{
DropShadowEffect dse = new DropShadowEffect
{
BlurRadius = 5,
ShadowDepth = 1,
Direction = 270,
Color =
(System.Windows.Media.Color)
convertFromString
};
_exampleImage = new Grid
{
Background =
new SolidColorBrush(SingleIcons.Helpers.ColorConverter.ToMediaColor(SelectedSectie.Color.ColorValue)),
VerticalAlignment = VerticalAlignment.Stretch,
Width = SelectedIconSize.Width,
Height = SelectedIconSize.Height,
MaxWidth = SelectedIconSize.Width,
MaxHeight = SelectedIconSize.Height,
HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch,
Effect = dse,
RowDefinitions =
{
new RowDefinition {Height = new GridLength(46, GridUnitType.Star)},
new RowDefinition {Height = new GridLength(3, GridUnitType.Star)}
}
};
}
TextBlock afbeeldingTextBlock = new TextBlock
{
Text = _selectedSectie.Sectie,
TextWrapping = TextWrapping.Wrap,
TextAlignment = TextAlignment.Center,
Width = _exampleImage.Width,
FontSize = Global.Fontsize,
FontFamily = new System.Windows.Media.FontFamily(Global.Family.Name),
VerticalAlignment = VerticalAlignment.Center,
Foreground =
new SolidColorBrush(
SingleIcons.Helpers.ColorConverter.ToMediaColor(SelectedSectie.Color.TextColorValue)),
};
TextOptions.SetTextFormattingMode(afbeeldingTextBlock, TextFormattingMode.Display);
TextOptions.SetTextRenderingMode(afbeeldingTextBlock, TextRenderingMode.ClearType);
Canvas bottomCanvas = new Canvas
{
Background = (SolidColorBrush) (new BrushConverter().ConvertFrom("#26000000"))
};
Grid.SetRow(afbeeldingTextBlock, 0);
Grid.SetRow(bottomCanvas, 1);
_exampleImage.Children.Add(afbeeldingTextBlock);
_exampleImage.Children.Add(bottomCanvas);
_exampleImage.Measure(new System.Windows.Size(_exampleImage.Width,
_exampleImage.Height));
_exampleImage.Arrange(
new Rect(new System.Windows.Size(_exampleImage.Width, _exampleImage.Height)));
return _exampleImage;
}
else
{
return null;
}
}
}
Now what I would like to do is to keep the grid at set dimensions but allow the GUI to scale the grid,
because when I make the window smaller the grid stays at these dimensions and it hurts the scaling of the application.
The reason I am using a databound grid is because I have another function which exports this grid to a .png.
Putting it inside a Viewbox and setting StretchDirection to DownOnly was the result i wanted.
<Grid x:Name="Example" Grid.Column="1" Grid.Row="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" >
<Viewbox StretchDirection="DownOnly" >
<ContentPresenter Content="{Binding ExampleImage}" />
</Viewbox>
</Grid>
I have a method which draws lines in a canvas like this:
public void drawoncanvas(double[] coord, string fullkey)
{
myLine = new Line();
myLine.X1 = coord[0];
myLine.X2 = coord[2];
myLine.Y1 = coord[1];
myLine.Y2 = coord[3];
MainWindow.mycanvas.Children.Add(myLine);
myLine.MouseEnter += mymouse; //add MousEnter Event
myLine.MouseLeave += mymouseleave; //add MouseLeave Event
}
The MouseEnter Event then adds a DropShadowEffect to the line that triggers the event:
public void mymouse(object sender, MouseEventArgs e)
{
Line thisline = sender as Line;
thisline.Effect = new DropShadowEffect{Color = new Color { A = 255, R = 255, G = 255, B = 0 }, Direction = 320,ShadowDepth = 0, Opacity = 1};
}
This works fine. But now I want to remove this effect as soon as the mouse cursor is not anymore over the line:
public void mymouseleave(object sender, MouseEventArgs e)
{
Line thisline = sender as Line;
thisline.Effect = null; //this doesn't do anything
}
I know this is a is probably a really simple question but I couldn't find any solution so far.
EDIT:
Ok I found what causes the problem, still don't know a solution though: I don't only create the dropshadow in the MouseEnter event but also display a tootltip, so my full Code is actually:
public void drawoncanvas(double[] coord, string fullkey)
{
myLine = new Line();
myLine.Stroke = Brushes.Red;
myLine.X1 = coord[0];
myLine.X2 = coord[2];
myLine.Y1 = coord[1];
myLine.Y2 = coord[3];
myLine.Tag = fullkey;
MainWindow.mycanvas.Children.Add(myLine);
myLine.MouseEnter += mymouse;
myLine.MouseLeave += mymouseleave;
}
ToolTip tt = new ToolTip();
public void mymouse(object sender, MouseEventArgs e)
{
Line thisline = sender as Line;
string data = Convert.ToString(thisline.Tag);
string[] splitdata = data.Split('/');
tt.Content = String.Concat(splitdata[0], " -> ", splitdata[3] ,"kt -> ", splitdata[1]);
tt.StaysOpen = false;
tt.IsOpen = true; //the removing of the shadow on MouseLeave works when I comment this line out
thisline.Effect = new DropShadowEffect{Color = new Color { A = 255, R = 255, G = 255, B = 0 }, Direction = 320,ShadowDepth = 0, Opacity = 1};
}
public void mymouseleave(object sender, MouseEventArgs e)
{
Line thisline = sender as Line;
tt.IsOpen = false;
thisline.Effect = null;
}
If I simply comment out the tt.IsOpen = true; and do not display the tooltip it all works fine.....I'm really confused.
EDIT 2:
Here the XAML:
<Window x:Class="mapO1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:mapO1"
Title="mapO1" Height="600" Width="750" WindowStartupLocation="CenterScreen" SizeChanged="MainWindow_SizeChanged">
<Grid>
<Grid x:Name="mygrid">
<local:ZoomBorder x:Name="border" ClipToBounds="True" Background="Black">
<Grid Name="maingrid">
<Image Name="image1" />
<Canvas Name="mycanvas" HorizontalAlignment="Left" VerticalAlignment="Top" ClipToBounds="False"/>
</Grid>
</local:ZoomBorder>
<Button x:Name="button1" Content="Fullscreen on/off" HorizontalAlignment="Right" Height="18" Margin="0,20,50,0" VerticalAlignment="Top" Opacity="0.5" Width="108" FontWeight="Bold" Click="button1_Click"/>
<ComboBox x:Name="comboBox1" Height="24" HorizontalAlignment="Left" VerticalAlignment="Top" Width="150" Margin="10,20,0,0" Opacity="0.5" FontWeight="Bold" Text="Select Period" SelectionChanged="comboBox1_SelectionChanged"/>
<ComboBox x:Name="comboBox2" Height="24" HorizontalAlignment="Left" VerticalAlignment="Top" Width="150" Margin="10,60,0,0" FontWeight="Bold" Opacity="0.5" Text="Select Stream" DropDownClosed="comboBox2_DropDownClosed"/>
</Grid>
</Grid>
</Window>
I have a WPF Canvas with a TextBlock and an Image on it. The text is animated, but it doesn't look smooth. I tried many combinations of different FPS-Settings and durations but it won't get better.
I also want to let the text fade-in/out at the start and ending. But I found no methods to do so.
At the moment it looks like that:
How can I get the animation smoothly? How can I fade it in/out smoothly?
Before you ask, I need to show the Window invisible because I use the WpfAppBar and that component needs an HWND.
Here is the canvas xaml:
<Canvas x:Name="canMain" HorizontalAlignment="Stretch" VerticalAlignment="Center">
<Border x:Name="boLogo" Panel.ZIndex="2" Height="40" Background="Gray" Canvas.Left="0" Canvas.Top="-20">
<Image Height="39" Width="auto" Margin="5, 0, 5, 0" Source="pack://siteoforigin:,,,/Resources/Logo.png" />
</Border>
<TextBlock x:Name="tbInfo" Panel.ZIndex="1" Visibility="Hidden" RenderOptions.BitmapScalingMode="NearestNeighbor" FontSize="32" TextOptions.TextFormattingMode="Display" TextOptions.TextRenderingMode="ClearType" FontFamily="Arial" FontWeight="Bold" Padding="5" HorizontalAlignment="Stretch" VerticalAlignment="Center">
<TextBlock.RenderTransform>
<TranslateTransform x:Name="AnimatedTranslateTransform" X="0" Y="0" />
</TextBlock.RenderTransform>
</TextBlock>
</Canvas>
And the code to animate the text:
public void ShowWindow(Brush fontColor, Brush backgroundColor, string str) {
var helper = new WindowInteropHelper(this);
helper.EnsureHandle();
tbInfo.Foreground = fontColor;
this.Background = backgroundColor;
tbInfo.Text = str;
this.Height = 39;
this.Width = SystemParameters.WorkArea.Width;
this.Left = SystemParameters.PrimaryScreenWidth - this.Width;
ShowWindowInvisible();
WpfAppBar.AppBarFunctions.SetAppBar(this, WpfAppBar.ABEdge.Top);
Visibility = Visibility.Visible;
int duration = 10 + str.Length / 5;
TextMarquee(duration);
}
private void TextMarquee(int duration)
{
Timeline.DesiredFrameRateProperty.OverrideMetadata(
typeof(Timeline),
new FrameworkPropertyMetadata { DefaultValue = 60 }
);
double height = canMain.ActualHeight - tbInfo.ActualHeight;
tbInfo.Margin = new Thickness(0, height / 2, 0, 0);
DoubleAnimation doubleAnimation = new DoubleAnimation();
doubleAnimation.From = canMain.ActualWidth;
doubleAnimation.To = tbInfo.ActualWidth *-1;
doubleAnimation.RepeatBehavior = RepeatBehavior.Forever;
doubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(duration));
tbInfo.BeginAnimation(Canvas.LeftProperty, doubleAnimation);
tbInfo.Visibility = Visibility.Visible;
}
private void ShowWindowInvisible()
{
var width = Width;
var height = Height;
var windowStyle = WindowStyle;
var showInTaskbar = ShowInTaskbar;
var showActivated = ShowActivated;
Width = 0;
Height = 0;
WindowStyle = WindowStyle.None;
ShowInTaskbar = false;
ShowActivated = false;
Show();
Visibility = Visibility.Hidden;
Width = width;
Height = height;
WindowStyle = windowStyle;
ShowInTaskbar = showInTaskbar;
ShowActivated = showActivated;
}