I have a UserControl that basically wraps a RichTextBox It looks something like this:
<UserControl x:Class="Installers.Ui.Views.Controls.RichTextBox"
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"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.Resources>
<ResourceDictionary Source="../../Theme/ElementsTheme.xaml"></ResourceDictionary>
</UserControl.Resources>
<RichTextBox x:Name="MyRichTextbox" Background="{StaticResource BackgroundColorBrush}" Foreground="{StaticResource GrayColorBrush}" BorderThickness="0" BorderBrush="Transparent">
</RichTextBox>
</UserControl>
I have some styling in the code behind, something that looks like:
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
var text = GetValue(RTFTextProperty).ToString();
var memoryStream = new MemoryStream(ASCIIEncoding.Default.GetBytes(text));
MyRichTextbox.Selection.Load(memoryStream, DataFormats.Rtf);
MyRichTextbox.IsReadOnly = IsReadOnly;
}
This is the outcome:
Now on to my question: As you can see there are "Boxes" around some of the text, How can I change the color of them to the background color or how can I remove them entirely?
Related
W11, VS2022
I'm fairly new to UI design in c#. I'm trying to draw a control at runtime and I can't seem to find the way to specify its x & y properties or set it to a Point.
xaml
<Page
x:Class="App1.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App1"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid>
<Grid x:Name="layoutRoot"></Grid>
</Grid>
</Page>
c# method
public MainPage()
{
this.InitializeComponent();
var ellipse1 = new Ellipse
{
Fill = new SolidColorBrush(Windows.UI.Colors.Pink),
Width = 200,
Height = 200
};
layoutRoot.Children.Add(ellipse1);
}
`
Have tried setleft, setright and location but they are all missing.
Thanks in Advance
Change it to Canvas
var ellipse1 = new Ellipse
{
Fill = new SolidColorBrush(Colors.Pink),
Width = 200,
Height = 200
};
int left = 50, top = 50;
Canvas.SetLeft(ellipse1, left); // second option Canvas.SetRight()
Canvas.SetTop(ellipse1, top); // second option Canvas.SetTop()
layoutRoot.Children.Add(ellipse1);
EDIT:
<Page
x:Class="App1.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App1"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Canvas x:Name="layoutRoot">
</Canvas>
</Page>
When trying to rebuild a WPF Application to use Caliburn Micro I experienced that a TextBox does not loose focus when you click outside of it. Is there a fix for that behaviour?
I am using Caliburn Micro 3.2.0. I tried using older versions but this problem persits.
XAML:
<Window x:Class="WPFUI.Views.ShellView"
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"
xmlns:local="clr-namespace:WPFUI.Views"
xmlns:cal="http://www.caliburnproject.org"
mc:Ignorable="d"
Title="ShellView" Height="450" Width="800">
<Grid>
...
<WrapPanel>
<TextBox x:Name="Name" MinWidth="50"
cal:Message.Attach="[Event LostFocus] = [Action Name_LostFocus()];
[Event PreviewTextInput] = [Action Name_PreviewTextInput($source, $eventArgs)]">
</TextBox>
...
</WrapPanel>
...
</Grid>
</Window>
I assume this is a case where you do not have any other Element in the Window other than the Textbox, which is why it cannot lose focus. One way to achieve this is to make the Window Focusable and setting Focus to it using a behavior.
For Example, assuming your Xaml to be as follows
<Window x:Class="CM.WPFApp2019.Views.ShellView"
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:cal="http://www.caliburnproject.org"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:CM.WPFApp2019.Views"
xmlns:i = "http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:behaviors="clr-namespace:CM.WPFApp2019.ViewModels"
mc:Ignorable="d" Focusable="True"
Title="ShellView" Height="450" Width="800">
<i:Interaction.Behaviors>
<behaviors:ClearFocusOnClickBehavior ElementToClearFocus="{Binding ElementName=Name}"/>
</i:Interaction.Behaviors>
<Grid>
<WrapPanel>
<TextBox x:Name="Name" MinWidth="50" Focusable="True"
cal:Message.Attach="[Event LostFocus] = [Action Name_LostFocus()];
[Event PreviewTextInput] = [Action Name_PreviewTextInput($source, $eventArgs)]">
</TextBox>
</WrapPanel>
</Grid>
</Window>
Please note I have added a Behavior called ClearFocusOnClickBehavior to the Window. Also you have set the Focusable Property of Window to be true.
Now you can define the behavior as follows
public class ClearFocusOnClickBehavior : Behavior<FrameworkElement>
{
public static readonly DependencyProperty ElementToClearFocusProperty = DependencyProperty.RegisterAttached("ElementToClearFocus", typeof(FrameworkElement),
typeof(ClearFocusOnClickBehavior), new UIPropertyMetadata());
public FrameworkElement ElementToClearFocus
{
get { return (FrameworkElement)GetValue(ElementToClearFocusProperty); }
set { SetValue(ElementToClearFocusProperty, value); }
}
protected override void OnAttached()
{
AssociatedObject.MouseDown += (sender, args) =>
{
FrameworkElement ctrl = ElementToClearFocus;
FrameworkElement parent = (FrameworkElement)ElementToClearFocus.Parent;
while (parent != null && parent is IInputElement
&& !((IInputElement)parent).Focusable)
{
parent = (FrameworkElement)parent.Parent;
}
DependencyObject scope = FocusManager.GetFocusScope(ElementToClearFocus);
FocusManager.SetFocusedElement(scope, parent as IInputElement);
};
base.OnAttached();
}
}
The Behavior would add a MouseDown event for the associated object, where you could trace the Parent of the ElementToClearFocus Control which can be Focused. In this case, since you have set the Window as focusable, it would receive the Focus. The Textbox in turn loses the focus and raises the Name_LostFocus method
I try to change the color of a canvas by pressing a button using command binding insted of click event to avoid any code behind in the MyView.xaml.cs file. The command is fireing and the messageboxes show the correct color code values before and after changing it so the new color is set but the color of the canvas do not change. If a use a click event and the code behind in the MyView.xaml.cs insted than all work fine but I would like to get it work wiht command bindning and without code behind in the MyView.xaml.cs file. How can I do that and what is that I am not doing right?
MainWindow.xaml
<Window x:Class="WpfApp1.MainWindow"
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"
xmlns:View="clr-namespace:WpfApp1.View"
xmlns:ViewModel="clr-namespace:WpfApp1.ViewModel"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525" Background="YellowGreen"
WindowStartupLocation="CenterScreen">
<Window.DataContext>
<ViewModel:MyClass/>
</Window.DataContext>
<View:MyView/>
</Window>
MyView.xaml file
<UserControl x:Class="WpfApp1.View.MyView"
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"
xmlns:ViewModel="clr-namespace:WpfApp1.ViewModel"
xmlns:View="clr-namespace:WpfApp1.View">
<Canvas Name="MainCanvas" Height="300" Width="502" Background="#FF148B63">
<Button Name="ChangeColorButton" Command="{Binding CommandChangeColor}" Content="new color" Height="25" Width="55" Margin="225,268,225,10"/>
</Canvas>
</UserControl>
MyClass.cs
public class MyClass : MyView
{
List<Color> _listOfColors = new List<Color>();
public MyClass(){ MyInitColor(); }
public ICommand CommandChangeColor
{
get { return new MyCommand(ChangeColor); }
}
public void ChangeColor()
{
MessageBox.Show("Color before: " + MainCanvas.Background.ToString());
Random rnd = new Random();
int i = rnd.Next(_listOfColors.Count - 1);
MainCanvas.Background = new SolidColorBrush(_listOfColors[i]);
MessageBox.Show("Color after: " + MainCanvas.Background.ToString());
}
}
Since you can have many instances of a UserControl, how would MyClass know which instance of MainCanvas it should be updating?
So similar to your binding for CommandChangeColor you should also bind the Background to some property in MyClass. Something like:
Xaml:
<Canvas Name="MainCanvas" Height="300" Width="502" Background="{Binding BackGroundColor}">
<Button Name="ChangeColorButton" Command="{Binding CommandChangeColor}" Content="new color" Height="25" Width="55" Margin="225,268,225,10"/>
</Canvas>
MyClass.cs
public SolidColorBrush BackGroundColor {get;set;}
public void ChangeColor()
{
MessageBox.Show("Color before: " + MainCanvas.Background.ToString());
Random rnd = new Random();
int i = rnd.Next(_listOfColors.Count - 1);
BackGroundColor = new SolidColorBrush(_listOfColors[i]);
MessageBox.Show("Color after: " + MainCanvas.Background.ToString());
}
You will probably also want to implement INotifyPropertyChanged.
I have a custom control CustomStackPanel which is a subclass of the StackPanel containing a CheckBox. The XAML is
<StackPanel x:Class="MyApp.CustomStackPanel"
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"
d:DesignHeight="300" d:DesignWidth="400" Orientation="Horizontal">
<CheckBox IsChecked="True">check me</CheckBox>
</StackPanel>
and the code behind doesn't do much:
namespace MyApp
{
public partial class CustomStackPanel: StackPanel
{
public CustomStackPanel()
{
InitializeComponent(); // added by Visual Studio
}
}
}
I can add the CustomStackPanel to the MainPage via XAML like
<local:CustomStackPanel />
and a CheckBox appears when I run the program. If instead I try to create a panel dynamically and add it to a container the CheckBox does not appear on the screen.
Old code:
...
StackPanel sp = new StackPanel();
sp.Add(new CheckBox());
somewhere.Add(sp);
...
--> I see a checkbox
New code:
...
somewhere.Add(new CustomStackPanel());
...
--> No checkbox
When the code is like this, the animation works as expected.
AnimatedUserControl2.xaml
<UserControl x:Class="WpfPoc20120908.AnimatedUserControl2"
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"
d:DesignHeight="300" d:DesignWidth="300" IsVisibleChanged="AnimatedUserControl2_OnIsVisibleChanged">
<Grid Background="Coral">
<Canvas>
<TextBlock x:Name="MNB" Text="ABCD"/>
</Canvas>
</Grid>
</UserControl>
AnimatedUserControl2.xaml.cs (Partial Code Only)
private void AnimatedUserControl2_OnIsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
{
if (Visibility == Visibility.Visible)
{
var storyboard = new Storyboard();
var visibilityAnimation = new ObjectAnimationUsingKeyFrames();
visibilityAnimation.KeyFrames.Add(new DiscreteObjectKeyFrame(Visibility.Visible,
KeyTime.FromTimeSpan(TimeSpan.FromSeconds(0))));
Storyboard.SetTargetProperty(visibilityAnimation, new PropertyPath(VisibilityProperty));
storyboard.Children.Add(visibilityAnimation);
var opacityAnimation = new DoubleAnimation(0, 1, new Duration(TimeSpan.FromSeconds(1)));
Storyboard.SetTargetProperty(opacityAnimation, new PropertyPath(OpacityProperty));
storyboard.Children.Add(opacityAnimation);
var canvasLeftAnimation = new DoubleAnimationUsingKeyFrames();
canvasLeftAnimation.KeyFrames.Add(new LinearDoubleKeyFrame(200,
KeyTime.FromTimeSpan(TimeSpan.FromSeconds(0))));
canvasLeftAnimation.KeyFrames.Add(new SplineDoubleKeyFrame(0, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(1)),
new KeySpline(new Point(0.25, 0.1),
new Point(0.25, 1))));
Storyboard.SetTargetProperty(canvasLeftAnimation, new PropertyPath(Canvas.LeftProperty));
storyboard.Children.Add(canvasLeftAnimation);
MNB.BeginStoryboard(storyboard, HandoffBehavior.SnapshotAndReplace, false);
}
}
However, when I use a ContentPresenter in the XAML code, the animation does not work at all.
AnimationUserControl2.xaml (1st Revision)
<UserControl x:Class="WpfPoc20120908.AnimatedUserControl2"
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"
d:DesignHeight="300" d:DesignWidth="300" IsVisibleChanged="AnimatedUserControl2_OnIsVisibleChanged">
<Grid Background="Coral">
<Canvas>
<ContentPresenter x:Name="MNB"/>
</Canvas>
</Grid>
</UserControl>
When I try to wrap the ContentPresenter with a Grid, the animation still doesn't work.
AnimationUserControl2.xaml (2nd Revision)
<UserControl x:Class="WpfPoc20120908.AnimatedUserControl2"
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"
d:DesignHeight="300" d:DesignWidth="300" IsVisibleChanged="AnimatedUserControl2_OnIsVisibleChanged">
<Grid Background="Coral">
<Canvas>
<Grid x:Name="MNB">
<ContentPresenter/>
</Grid>
</Canvas>
</Grid>
</UserControl>
Here's the question. How can I get the animation to work with a ContentPresenter?
UPDATE 01
Here's how AnimatedUserControl2 is used.
MainWindow.xaml (Partial Code Only)
<StackPanel Grid.Row="0" Orientation="Vertical">
<usercontrols:AnimatedUserControl2 x:Name="ABCD" Visibility="Hidden">
<TextBlock Text="ABC"/>
</usercontrols:AnimatedUserControl2>
<usercontrols:AnimatedUserControl2 x:Name="EFGH" Visibility="Hidden" Margin="10">
<TextBlock Text="ABC"/>
</usercontrols:AnimatedUserControl2>
</StackPanel>
<Button x:Name="ButtonBeginAnimation" Click="ButtonBeginAnimation_OnClick" Content="Begin Animation" Grid.Row="1"/>
MainWindow.xaml.cs (Partial Code Only)
private void ButtonBeginAnimation_OnClick(object sender, RoutedEventArgs e)
{
ABCD.Visibility = (ABCD.Visibility == Visibility.Visible) ? Visibility.Collapsed : Visibility.Visible;
EFGH.Visibility = (EFGH.Visibility == Visibility.Visible) ? Visibility.Collapsed : Visibility.Visible;
}
So the problem is with how you're using your user control - you simply override content once specified inside UserControl xaml definition... anyway..
Try this approach (animation works on my machine so suppose to work on yours as well ;))
<UserControl x:Class="WpfApplication11.UserControl1"
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"
d:DesignHeight="300"
d:DesignWidth="300"
mc:Ignorable="d">
<UserControl.Template>
<ControlTemplate TargetType="UserControl">
<Grid Background="Coral">
<Canvas>
<ContentPresenter x:Name="MNB" Content="{TemplateBinding Content}"/>
</Canvas>
</Grid>
</ControlTemplate>
</UserControl.Template>
And in animation itself:
private void AnimatedUserControl2_OnIsVisibleChanged(object sender, EventArgs e)
{
var mnb = Template.FindName("MNB", this) as FrameworkElement;
if (mnb == null)
{
return;
}
if (Visibility == Visibility.Visible)
{
var storyboard = new Storyboard();
var visibilityAnimation = new ObjectAnimationUsingKeyFrames();
visibilityAnimation.KeyFrames.Add(new DiscreteObjectKeyFrame(Visibility.Visible,
KeyTime.FromTimeSpan(TimeSpan.FromSeconds(0))));
Storyboard.SetTargetProperty(visibilityAnimation, new PropertyPath(VisibilityProperty));
storyboard.Children.Add(visibilityAnimation);
var opacityAnimation = new DoubleAnimation(0, 1, new Duration(TimeSpan.FromSeconds(1)));
Storyboard.SetTargetProperty(opacityAnimation, new PropertyPath(OpacityProperty));
storyboard.Children.Add(opacityAnimation);
var canvasLeftAnimation = new DoubleAnimationUsingKeyFrames();
canvasLeftAnimation.KeyFrames.Add(new LinearDoubleKeyFrame(200,
KeyTime.FromTimeSpan(TimeSpan.FromSeconds(0))));
canvasLeftAnimation.KeyFrames.Add(new SplineDoubleKeyFrame(0, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(1)),
new KeySpline(new Point(0.25, 0.1),
new Point(0.25, 1))));
Storyboard.SetTargetProperty(canvasLeftAnimation, new PropertyPath(Canvas.LeftProperty));
storyboard.Children.Add(canvasLeftAnimation);
mnb.BeginStoryboard(storyboard, HandoffBehavior.SnapshotAndReplace, false);
}
}