C# WPF add control to main window at run time - c#

My goal is to attach a new image control while the application is running.
img = new System.Windows.Controls.Image();
img.Margin = new Thickness(200, 10, 0, 0);
img.Width = 32;
img.Height = 32;
img.Source = etc;
I've tried
this.AddChild(img);// says must be a single element
this.AddLogicalChild(img);// does nothing
this.AddVisualChild(img);// does nothing
It was never this difficult to add a element with forms.
How can I simply attach this new element to the main window (not another control) so that it will show up.
Solved it, I named the grid main, and from there I was able to access the children attribute and the add function
main.children.add(img);
<Window x:Class="Crysis_Menu.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525" Loaded="Window_Loaded" AllowsTransparency="False" Background="White" Foreground="{x:Null}" WindowStyle="SingleBorderWindow">
<Grid Name="main">
<Button Content="Run" Height="23" HorizontalAlignment="Left" Margin="12,12,0,0" Name="btnRun" VerticalAlignment="Top" Width="151" Click="btnRun_Click" />
<TextBox Height="259" HorizontalAlignment="Left" Margin="12,40,0,0" Name="tbStatus" VerticalAlignment="Top" Width="151" />
</Grid>
</Window>

You should have only one root element under window. Adding the image using this.AddChilda adds the image as child of window, but you probably have some other child defined(Grid for example). Give a name to this child (Grid in the example) and then in the code behind add the image to the Grid
Example :
<Window>
<Grid x:Name="RootGrid">
</Grid>
</Window>
Then in the code behind use
RootGrid.Children.Add(img);

What is this in your case? You can try this.Content = image; or this.Children.Add(image);
If your this is indeed a Window, you should know that Window can have only a single child, which you put into Content. If you want several items in Window, usually you put some appropriate container (for example, Grid or StackPanel) as Window's content, and add children to it.

Vlad got the solution. I used it :
var grid = this.Content as Grid;
// or any controls
Label lblMessage = new Label
{
Content = "I am a label",
Margin = new Thickness(86, 269, 0, 0)
};
grid.Children.Add(lblMessage);

Related

FlowDocument has too much white space on lines

Following btnTest_Click(...) event in my WPF .NET5 app successfully displays the content of a RichTextBox into a FlowDocumentReader. But, as shown in the images below, the different page viewing modes of the FlowDocumentReader create excessive amounts of whitespace on lines. Question: Why it is happening, what I may be missing here, and how can we resolve the issue?
MainWindow.xaml
<Window x:Class="Wpf_RTBFlowDocTest.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"
xmlns:local="clr-namespace:Wpf_RTBFlowDocTest"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<DockPanel Name="mainPanel">
<ToolBar Name="mainToolBar" Height="30" DockPanel.Dock="Top">
<Button x:Name="btnTest" Content="Test" Click="btnTest_Click"/>
</ToolBar>
<RichTextBox Name="rtbTest" AcceptsTab="True" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto"/>
<FlowDocumentReader x:Name="fdReader" ScrollViewer.VerticalScrollBarVisibility="Auto" IsScrollViewEnabled="True">
<FlowDocument IsOptimalParagraphEnabled="True" IsHyphenationEnabled="True" TextAlignment="Left"></FlowDocument>
</FlowDocumentReader>
</DockPanel>
</Grid>
</Window>
MainWindow.xaml.cs
private void btnTest_Click(object sender, RoutedEventArgs e)
{
var range = new TextRange(rtbTest.Document.ContentStart, rtbTest.Document.ContentEnd);
if (!range.IsEmpty)
{
if(fdReader.Document.Blocks.Count > 0)
fdReader.Document.Blocks.Clear();
using (var stream = new MemoryStream())
{
range.Save(stream, DataFormats.XamlPackage);
var copyto = new TextRange(fdReader.Document.ContentEnd, fdReader.Document.ContentEnd);
copyto.Load(stream, DataFormats.XamlPackage);
}
}
rtbTest.Visibility = Visibility.Collapsed;
fdReader.Visibility = Visibility.Visible;
}
Original display of the app before clicking the Test button:
Single pageview display after the above code ran:
Single Scroll pageview display after above code ran:
Multiple pageview display after the above code ran:
That's exactly as expected: your source text file is including lots of NewLine characters for line feed inside the sentences and spaces used for lines content alignment:
In a flow document, the content adapts itself to fit the container, but NewLine characters inside sentences prevented the FlowDocument control to format the text correctly.
Therefore, it's necessary to make some source text processing before loading it to the FlowDocument control.

How to show relative source image on WPF hosted by WinForm Project without modifying behind code?

I made WinForm project and add ElementHost for using WPF blend effect on some Images.
ElementHost m_host = new ElementHost();
WPF_TK4S wpfTK4S = new WPF_TK4S();
m_host.Child = wpfTK4S;
m_host.Size = new Size(1000, 1000);
m_host.Location = new Point(0, 0);
this.Controls.Add(m_host);
I added the image control on WPF user control like below.
<UserControl x:Class="Test.WPF_TK4S"
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="1000" d:DesignWidth="1000">
<Grid>
<Grid.Background>
<ImageBrush/>
</Grid.Background>
<Image Source="/Resources/TK4S_254X253.png" HorizontalAlignment="Left" Height="344" Margin="48,44,0,0" VerticalAlignment="Top" Width="342" Stretch="None"/>
</Grid>
The image is shown well on control view but is now shown when I run the application.
Fortunately, after I changed the source uri into absolute uri like
"D://Visual Project/Test/Test/Resources/TK4S_254X253.png"
the image is shown well!!
I tried to use all kinds of relative uri like
".../Test/Resources/TK4S_254X253.png", "pack://application:,,,/TK4S_254X253.png"
but it is not work.
I need to use relative path because the project is operating on Server so every project paths are different. And I have to use this things on xaml because I have to use blend after the image is initialized.
Does anything I need to know other option?

Scrollbars in a dynamically filled stack panel

I am new for WPF so apologies if the answer is so obvious.
I got a WPF resizable window with a single stack panel control that is stretched vertically and horizontally to fill the window.
On window activated event, I use ".Children.Add" to add button controls to the panel. I have no idea how many buttons will be there at runtime so I checked "CanVerticallyScroll" in the panel. ScrollViewer.VerticalScrollBarVisibility is set to Visible by default.
I am still not seeing scroll bars at runtime though.
What properties did I miss to show scrolling panel with buttons?
Thanks
XAML:
<Window x:Class="ResMed.Ecp.Utility.ConnectionWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="ConnectionWindow" Height="388" Width="641.6" Activated="Window_Activated">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="359*"/>
</Grid.RowDefinitions>
<StackPanel x:Name="pnlConnectionButtons" Margin="10,10.2,10.2,10" Grid.Row="1" CanVerticallyScroll="True"/>
</Grid>
</Window>
Code behind:
private void Window_Activated(object sender, EventArgs e)
{
for (int i = 0; i < 20; i++)
{
Button btn = new Button();
btn.Content = "Hello";
pnlConnectionButtons.Children.Add(btn);
}
}
Place your StackPanel inside a ScrollViewer:
<ScrollViewer>
<StackPanel>
<Button Content="Hello World"></Button>
...
...
</StackPanel>
</ScrollViewer>
You can also remove CanVerticallyScroll="True". From MSDN:
This property is not intended for use in your code. It is exposed publicly to fulfill an interface contract (IScrollInfo). Setting this property has no effect.

Window opened with showDialog, TextBlock is showing underneath window instead of text

I have this wierd wpf problem.
I have a window (full screennm) with an Image, looks like this:
I open a new window with Showdialog uppon this window, which is not full screen (looks like a popup, but its a window). the code is like this:
Window next; next = new PasswordVerification();
next.Owner = this;
next.ShowDialog();
on the open window I use this to center the "popup":
this.Left = this.Owner.Left + (this.Owner.Width - this.ActualWidth) / 2;
this.Top = this.Owner.Top + (this.Owner.Height - this.ActualHeight) / 2;
this.Topmost = true;
I get something like this ( i cropped it, the window is slight bigger):
Where the textblock is defined like this:
<Rectangle Name="errorBorder" Fill="#34FF0000" FlowDirection="RightToLeft" RadiusX="13" RadiusY="13" Stroke="#FFB80005" Visibility="Visible" Margin="43,195,78,203" />
<TextBlock Name="error" Text="TextBlock" Margin="49,195,91,205" FontSize="20" FlowDirection="RightToLeft" FontWeight="Bold" Foreground="#FFB80000" Visibility="Visible" />
Now I have a button, that does this:
error.Text = "blabla";
But instead of what I expected (that the Text will change) I get this wierd stuff:
As you can see, The image from the rear window is sligtly shown, instead of my textBlock!
What is going on here??Please Help!
The PopUp XAML:
<Window ... Width="1000" Height="700" AllowsTransparency="True"
WindowStyle="None"
Background="#00000000"/>
<Border Style="{StaticResource SmallScreenBorderStyle}" CornerRadius="23" Padding="2" Margin="153.66,117.992,153.661,117.992" d:LayoutOverrides="Width, Height">
<!-- Use a VisualBrush of 'mask' as the opacity mask -->
<Grid.OpacityMask>
<VisualBrush Visual="{Binding ElementName=mask}"/>
</Grid.OpacityMask>
<!-- Rounded mask (stretches to fill Grid) to make grid rounded corners -->
<Border x:Name="mask" CornerRadius="20" Margin="2,5,-1,-5" d:LayoutOverrides="GridBox" Style="{StaticResource MaskBorderStyle}"/>
Few suggestions:
1) Remove your code to open window at center of owner, just use this in your Window XAML:
<Window ....
WindowStartupLocation="CenterOwner">
2) Shorten your calling method:
Window next = new PasswordVerification {Owner = this};
next.ShowDialog();
3) Put your Rectangle and TextBlock in <StackPanel> or another container. Probably the problem that these controls overlaps because lives inside Grid.
Could you try setting the Visible property to false on your your main form, and then setting it back to true after your ShowDialog?

WPF Change Thickness object in Resource and assign in code behind

I have defined one Thickness resource in Window's resources collection which is set to value 10 along all sides. I have 3 Buttons in that window.
Upon clicking the third button, I am fetching the value of that resource, changing it(200, all edges) and applying it statically for first button and dynamically for second but still it's picking up the old value(10) for the button which is using it dynamically. For Buttton using it statically it was supposed to fetch the old value (10) but I thought just because the second button is fetching it dynamically, it will reflect the change(200).
<Window x:Class="WpfApplicationUnleashed.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:sys="clr-namespace:System;assembly=mscorlib" xmlns:local="clr-namespace:WpfApplicationUnleashed"
Title="Window1" >
<Window.Resources>
<Thickness x:Key="BadiThickness">10</Thickness>
</Window.Resources>
<StackPanel>
<Button x:Name="cmdStatic" HorizontalAlignment="Center" >
I am Static
</Button
<Button x:Name="cmdDynamic" HorizontalAlignment="Center" >
I am Dynamic
</Button>
<Button x:Name="cmdChanger" HorizontalAlignment="Center" Click="cmdChanger_Click">
I am Changer
</Button>
</StackPanel>
</Window>
Code:
private void cmdChanger_Click(object sender, RoutedEventArgs e)
{
Thickness th = (Thickness)this.FindResource("BadiThickness");
th.Bottom = 200;
th.Top = 200;
th.Left = 200;
th.Right = 200;
cmdDynamic.SetResourceReference(Button.MarginProperty, "BadiThickness");
cmdStatic.Margin = (Thickness)this.FindResource("BadiThickness");
}
You do realize that Thickness is a value type and that is why when you change it's value, it won't be affected in the resource.
What you can do to set that resource's value is following:
this.Resource["BadiThickness"] = new Thickness(200);
On a side note, please avoid using Hindi in a resource's name. That may mislead.

Categories

Resources