Why does the stackpanel ignore Orientation property? - c#

I'd like to use a stackpanel with two textblock that have two uris, inside a ContentDialog. The problem is that despite I set the property to Vertical, it has no effect and that's the visual result
private async void AboutButton_Click(object sender, RoutedEventArgs e)
{
TextBlock gHRepoTB = new TextBlock();
Hyperlink hyperlink1 = new Hyperlink();
Run run1 = new Run();
run1.Text = "View GitHub repository";
hyperlink1.NavigateUri = new Uri("https://www.google.com/");
hyperlink1.Inlines.Add(run1);
gHRepoTB.Inlines.Add(hyperlink1);
TextBlock privacyPolicyTB = new TextBlock();
Hyperlink hyperlink2 = new Hyperlink();
Run run2 = new Run();
run2.Text = "Privacy Policy";
hyperlink2.NavigateUri = new Uri("https://www.bing.com/");
hyperlink2.Inlines.Add(run2);
gHRepoTB.Inlines.Add(hyperlink2);
StackPanel aboutPanel = new StackPanel();
aboutPanel.Orientation = Orientation.Vertical;
aboutPanel.Children.Add(gHRepoTB);
aboutPanel.Children.Add(privacyPolicyTB);
ContentDialog aboutDialog = new ContentDialog();
aboutDialog.Title = "About";
aboutDialog.Content = aboutPanel;
aboutDialog.PrimaryButtonText = "Report a bug";
aboutDialog.PrimaryButtonClick += ReportBug_Click;
aboutDialog.PrimaryButtonStyle = App.Current.Resources["AccentButtonStyle"] as Style;
aboutDialog.CloseButtonText = "Close";
await aboutDialog.ShowAsync();
}

#mm8 showed how to fix your problem, however this is the result of unnecessary and unclear code.
Here are the things I changed:
I've changed a button with hyperlink layout to a hyperlinkbutton.
I've set the contents to just a string since in this case no more is needed.
Instead of manually setting a style to the primarybutton, I've specified the DefaultButton
By creating the dialog this way, you are less prone to making mistakes, others and yourself later on will be able to tell faster what's going on, and less temporary variables are introduced.
The code (You should be able to copy this code directly over your current eventhandler):
private async void AboutButton_Click(object sender, RoutedEventArgs e)
{
StackPanel aboutPanel = new StackPanel();
aboutPanel.Children.Add(
new HyperlinkButton
{
Content = "View GitHub repository",
NavigateUri = new Uri("https://www.google.com/")
});
aboutPanel.Children.Add(
new HyperlinkButton
{
Content = "Privacy Policy",
NavigateUri = new Uri("https://www.bing.com/")
});
var dlg = new ContentDialog
{
Title = "About",
Content = aboutPanel,
PrimaryButtonText = "Report a bug",
DefaultButton = ContentDialogButton.Primary,
CloseButtonText = "Close"
};
dlg.PrimaryButtonClick += ReportBug_Click;
await dlg.ShowAsync();
}
See the result below:

You add the second Hyperlink to the wrong TextBlock. It should be privacyPolicyTB.Inlines.Add(hyperlink2);:
TextBlock privacyPolicyTB = new TextBlock();
Hyperlink hyperlink2 = new Hyperlink();
Run run2 = new Run();
run2.Text = "Privacy Policy";
hyperlink2.NavigateUri = new Uri("https://www.bing.com/");
hyperlink2.Inlines.Add(run2);
privacyPolicyTB.Inlines.Add(hyperlink2); //<-- here

Related

Winform: Clean way to toggle visibility of a control on TextChanged in TextBox

I have a winform with many TextBox and a single message, I want the message to disappear when any of the TextBox are changed. Is there a clean way to achieve this without adding TextChanged EventHander to all TextBox ?
My messy way of doing it is as follows:
public static DialogResult ShowDialog()
{
var inputBox = new Form { ClientSize = new Size(520, 225), FormBorderStyle = FormBorderStyle.FixedDialog };
var input1 = new TextBox { Location = new Point(25, 25)};
var input2 = new TextBox { Location = new Point(25, 60) };
// Many more text boxes...
var label = new Label { Text = "Text", Location = new Point(25, 90), Visible = true };
input1.TextChanged += new EventHandler((sender, e) => label.Visible = false);
input2.TextChanged += new EventHandler((sender, e) => label.Visible = false);
// Add handler for all TextBoxes...
inputBox.Controls.Add(input1);
inputBox.Controls.Add(input2);
inputBox.Controls.Add(label);
return inputBox.ShowDialog();
}
You can try to write a function to create TextBox.
let TextBox initial setting and event binding code in the function.
private static TextBox CreateTextBox(int xPos,int yPos,Label label){
var input1 = new TextBox { Location = new Point(xPos, yPos)};
input1.TextChanged += new EventHandler((sender, e) => label.Visible = false);
return input1;
}
You just need to call the function in inputBox.Controls.Add method,and pass parameters which you need.
public static DialogResult ShowDialog()
{
var inputBox = new Form { ClientSize = new Size(520, 225), FormBorderStyle = FormBorderStyle.FixedDialog };
var label = new Label { Text = "Text", Location = new Point(25, 90), Visible = true };
inputBox.Controls.Add(CreateTextBox(25, 25,label));
inputBox.Controls.Add(CreateTextBox(25, 60,label));
inputBox.Controls.Add(label);
return inputBox.ShowDialog();
}
NOTE
if there are too many parameters you can try to use a class to carry those and pass.

Get the text from clicked Hyperlink

I created some Hyperlinks using the code below:
public Class_List()
{
InitializeComponent();
StackPanel myStackPanel = new StackPanel();
TextBlock txt = new TextBlock();
txt.Foreground = Brushes.Black;
txt.FontFamily = new FontFamily("03SmartFontUI");
txt.FontSize = 25;
txt.Margin = new Thickness(0, 5, 0, 5);
Run run = new Run(className);
Hyperlink link = new Hyperlink(run);
link.Click += Link_Click;
txt.Inlines.Add(link);
}
Now, I want to get the text of the hyperlink and store it on string s:
private void Link_Click(object sender, RoutedEventArgs e)
{
string s = (sender as Hyperlink).Inlines.ToString();
Class_Page class_page = new Class_Page();
NavigationService.Navigate(class_page);
}
However instead of the hyperlink text, I got
System.Windows.Documents.InlineCollection
You're getting that type because you are actually accessing the entire collection of Inlines rather than the Inline you're looking for. The fastest way to access the Run's text you're using as the first Inline in the Hyperlink's InlineCollection is to do this:
((sender as Hyperlink).Inlines.FirstInline as Run).Text;

Simple document using FastReport.Net does not show text

I tried to make a simple document using FastReport. So I started with placing a button on the form and writing the following code in order to run it when the button is clicked:
private void button1_Click(object sender, EventArgs e)
{
Report report = new Report();
ReportPage page1 = new ReportPage();
page1.Name = "Page1";
report.Pages.Add(page1);
page1.ReportTitle = new ReportTitleBand();
page1.ReportTitle.Name = "ReportTitle1";
TextObject text1 = new TextObject();
text1.Name = "Text1";
text1.Text = "REPORT TITLE TEXT";
text1.HorzAlign = HorzAlign.Center;
text1.Font = new Font("Tahoma", 14, FontStyle.Bold);
page1.ReportTitle.Objects.Add(text1);
report.Show();
}
Unfortunately, when I ran the application and I pressed the button, a blank page was shown, without any text. What is wrong with the code? Does it lack some element?
You should set width and height for text object:
text1.AutoWidth = true;
text1.Height = 100;

Use WPF expander in Winforms with more than one control

My problem is that I want to use WPF expander object to host some winforms control. And the position that I'm going to use this is in my application's setting form. But, what I couldn't find is to add more than one control to it.
After a lot of searching for solution to my problem I just found this simple code that only add one control to the WPF expander object (I require more than one control to be added):
private void Form1_Load(object sender, EventArgs e)
{
System.Windows.Controls.Expander expander = new System.Windows.Controls.Expander();
expander.Header = "Sample";
WPFHost = new ElementHost();
WPFHost.Dock = DockStyle.Fill;
WindowsFormsHost host = new WindowsFormsHost();
host.Child = new DateTimePicker();
expander.Content = host;
WPFHost.Child = expander;
this.Controls.Add(WPFHost);
}
In this code the expander only hosts one control.
How should I customize it to host more than one control ?
Please help
Using a System.Windows.Forms.Panel as a container will help:
private void Form1_Load(object sender, EventArgs e)
{
System.Windows.Controls.Expander expander = new System.Windows.Controls.Expander();
System.Windows.Controls.Grid grid = new System.Windows.Controls.Grid();
expander.Header = "Sample";
ElementHost WPFHost = new ElementHost();
WPFHost.Dock = DockStyle.Fill;
Panel panel1 = new Panel();
DateTimePicker dtPicker1 = new DateTimePicker();
Label label1 = new Label();
// Initialize the Label and TextBox controls.
label1.Location = new System.Drawing.Point(16, 16);
label1.Text = "Select a date:";
label1.Size = new System.Drawing.Size(104, 16);
dtPicker1.Location = new System.Drawing.Point(16, 32);
dtPicker1.Text = "";
dtPicker1.Size = new System.Drawing.Size(152, 20);
// Add the Panel control to the form.
this.Controls.Add(panel1);
// Add the Label and TextBox controls to the Panel.
panel1.Controls.Add(label1);
panel1.Controls.Add(dtPicker1);
WindowsFormsHost host = new WindowsFormsHost();
host.Child = panel1;
expander.Content = host;
WPFHost.Child = expander;
this.Controls.Add(WPFHost);
}

WPF code-only app GIVES "Object reference not set to an instance of an object."

I am trying to create a code-only WPF app but am getting the above error when I type in the textBox. This is though ALL my variables are initialized.
The windows1.xaml is this:
<?xml version="1.0" encoding="utf-8"?>
<Window>
x:Class="BlendCatalogue.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="BlendCatalogue"
Height="300"
Width="300">
</Window>
The code behind is this:
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
namespace BlendCatalogue
{
public partial class Window1 : Window
{
private TextBlock textBlock;
private TextBox textBox;
public Window1()
{
InitializeComponent();
Initialization();
}
public void Initialization()
{
this.Width=300;
this.Height=200;
this.Background =Brushes.Aquamarine;
this.Title = "Only the best!";
Grid layoutGrid = new Grid();
StackPanel stackpanel = new StackPanel();
layoutGrid.Children.Add(stackpanel);
this.AddChild(layoutGrid);
TextBlock textBlock = new TextBlock();
textBlock.Margin = new Thickness(6);
textBlock.Height = 20;
textBlock.TextAlignment = TextAlignment.Center;
textBlock.Text = "Hello my World!";
stackpanel.Children.Add(textBlock);
TextBox textBox = new TextBox();
textBox.Margin = new Thickness(5);
textBox.Width = 150;
textBox.TextAlignment = TextAlignment.Center;
textBox.Text = "";
textBox.TextChanged += OnTextChanged;
stackpanel.Children.Add(textBox);
Button btnColor = new Button();
btnColor.Margin = new Thickness(5);
btnColor.Width = 150;
btnColor.Content = "Change Text Color";
btnColor.Click += btnChangeColor_Click;
stackpanel.Children.Add(btnColor);
Button btnSize = new Button();
btnSize.Margin = new Thickness(5);
btnSize.Width = 150;
btnSize.Content = "Change Text Color";
btnSize.Click += btnChangeSize_Click;
stackpanel.Children.Add(btnSize);
}
private void OnTextChanged(object sender, TextChangedEventArgs e)
{
textBlock.Text = textBox.Text;
}
private void btnChangeColor_Click(object sender, RoutedEventArgs e)
{
if (textBlock.Foreground == Brushes.Black)
textBlock.Foreground = Brushes.Red;
else
textBlock.Foreground = Brushes.Black;
}
private void btnChangeSize_Click(object sender, RoutedEventArgs e)
{
if (textBlock.FontSize == 11)
textBlock.FontSize = 42;
else
textBlock.FontSize = 11;
}
}
}
This newbie simply does not know what is being done wrong and would really appreciate any help.
Thanks all.
Your are creating two TextBlock's and two TextBox's one with Module level scope and one with Local scope. You then initialize the one with Local scope and try to use the one with Module level scope causing your error.
Try changing your code in your Initialization Method to:
textBlock = new TextBlock();
textBlock.Margin = new Thickness(6);
textBlock.Height = 20;
textBlock.TextAlignment = TextAlignment.Center;
textBlock.Text = "Hello my World!";
stackpanel.Children.Add(textBlock);
textBox = new TextBox();
textBox.Margin = new Thickness(5);
textBox.Width = 150;
textBox.TextAlignment = TextAlignment.Center;
textBox.Text = "";
textBox.TextChanged += OnTextChanged;
stackpanel.Children.Add(textBox);
You declare some of your variables twice:
private TextBlock textBlock;
private TextBox textBox;
TextBlock textBlock = new TextBlock();
TextBox textBox = new TextBox();
You initialize the ones that are scoped to Initialize() but access the class level variables in your event handlers.
Change
TextBlock textBlock = new TextBlock();
TextBox textBox = new TextBox();
to
textBlock = new TextBlock();
textBox = new TextBox();
Note that you should have gotten compiler warnings like
warning CS0649: Field 'BlendCatalogue.Window1.textBlock' is never assigned to, and will always have its default value null
The compiler was trying to help you out... :-)

Categories

Resources