How to generate WPF controls automatically based on XML file? - c#

I have an Xml file which tells me the controls that I have to add to a form but this Xml changes dynamically and I need to update the form.
Currently, I can read the XML file, but I dont know if it is possible to automatically create forms based on that or not ?

Yes It is possible.
WPF offers several ways of creating controls either in Xaml or in code.
For your case if you need to dynamically create your controls, you'll have to create them in code. You can either create your control directly using their constructors as in:
// Create a button.
Button myButton= new Button();
// Set properties.
myButton.Content = "Click Me!";
// Add created button to a previously created container.
myStackPanel.Children.Add(myButton);
Or you could create your controls as a string containing xaml and use a XamlReader to parse the string and create the desired control:
// Create a stringBuilder
StringBuilder sb = new StringBuilder();
// use xaml to declare a button as string containing xaml
sb.Append(#"<Button xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml' ");
sb.Append(#"Content='Click Me!' />");
// Create a button using a XamlReader
Button myButton = (Button)XamlReader.Parse(sb.ToString());
// Add created button to previously created container.
stackPanel.Children.Add(myButton);
Now for which one of the two methods you want to use really depends on you.
Jean-Louis

You can easily add controls via code in wpf, you can follow this article. Another thing worth noting is that XAML is a form of XML so you can you save your XAML to an XML file, that way you wouldn't need to add controls in code, however it depends on the complexity of your application.

I am pretty new to Xaml but to add to Jean-Louis's answer if you do not want to add the namespaces to every element string then you can do something like this using the System.Windows.Markup namespace:
ParserContext context = new ParserContext();
context.XmlnsDictionary.Add("", "http://schemas.microsoft.com/winfx/2006/xaml/presentation");
context.XmlnsDictionary.Add("x", "http://schemas.microsoft.com/winfx/2006/xaml");
string xaml = String.Format(#"<ListBoxItem Name='Item{0}' Content='{1}' />", itemID, listItems[itemID]);
UIElement element = (UIElement)XamlReader.Parse(xaml, context);
listBoxElement.Items.Add(element);

Adding controls through the Children.Add method is the quickest way i've found, such as for example
this.Grid.Add(new TextBox() { Text = "Babau" });

Related

How to add link Labels at run time in Windows form

I have been making a Windows Form Application in C# using the Visual C# 2008 IDE.
There are basically two forms in my application. One is created at Runtime and it's layout is undefined and the second one's predefined.
Now, I have been adding form elements using the toolbox provided and don't have any idea how to add them using written code(not using toolbox). I want to add n number of Labels to the second form which is undefined. n can be anything(decided at runtime, depending on the user's input). Can anybody tell me what is the efficient way to do this?
Just a quick example of a "dynamic control" being created at run-time and added to the form:
Label lbl = new Label();
lbl.Text = "Hello World!";
lbl.Location = new Point(100, 25);
this.Controls.Add(lbl);
You can replace "this" with the container to add it to, like "panel1" for instance. For containers that have their own layout engine, like a FlowLayoutPanel, then you wouldn't need to specify a Location().
Create a new LinkLabel(), set its properties (in particular, text and position), then add it to the Controls collection of your form or any panel.
You may also want to add event handlers, and store them somewhere (probably in a List<T>) so you can change or remove them later.
Create one in the designer, configure it's properties as you wish. Then go to the designer file, which name is like Form1.Desiner.cs, copy the code related to your LinkLabel (find everything with text search) and paste it where you wish :)

WPF cut, copy, paste functionality on a user control

I have a canvas on which you can add UserControls (consists of images and textboxes)
Im trying to implement cut, copy, paste functionality on these UserControls, so the context menu is attatched to a UserControl which deals with images for example. A user right clicks here and from the context menu picks copy for instance how would I then go about implementing so they can paste this on to the canvas.
Can anyone point me in the right direction...
This can be done with RoutedCommands. A full overview is at MSDN: Commanding Overview
The short version is this: when a command source (i.e. a menu item) wants to execute a command, an event is raised. That event is handled by the nearest command binding. Cut/copy/paste commands are already included with WPF, and certain elements (namely, text boxes) already include command bindings for them.
You can define a menu item like this:
<MenuItem Header="Copy" Command="ApplicationCommands.Copy" />
And add a command binding to the UserControl like this:
<UserControl.CommandBindings>
<CommandBinding Command="ApplicationCommands.Copy"
Executed="Copy_Executed" />
</UserControl.CommandBindings>
And define the Copy_Executed method with the ExecutedRoutedEventHandler signature in the UserControl's code-behind.
Then of course do the same thing for ApplicationCommands.Paste within the canvas.
It's up to you whether you want to handle the data within your own application, or use the clipboard. If you're working with images, WPF has a Clipboard class which can work with BitmapSource objects (if you have an Image element, chances are its Source is already a BitmapSource).
Firstly, a well designed MVVM application can make copy/paste of user controls much simpler since it will turn to serialize/deserialize CLR objects to Clipboard. WPF will handle user control creation by itself after deserialization.
If your application does not implement MVVM. You can use XamlWriter/XamlReader to save user controls to XAML and recreate them by yourself. An example:
StringBuilder outstr = new StringBuilder();
//this code need for right XML fomating
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
settings.OmitXmlDeclaration = true;
XamlDesignerSerializationManager dsm =
new XamlDesignerSerializationManager(XmlWriter.Create(outstr, settings));
//this string need for turning on expression saving mode
dsm.XamlWriterMode = XamlWriterMode.Expression;
XamlWriter.Save(control, dsm);
//Read control from XAML
var frameObject = XamlReader.Parse(outstr.ToString()) as UserControl;
if (frameObject != null)
stackPanel.Children.Add(frameObject);
For the part of how to put the XAML string or serialized stream into Clipboard, you can refer to MSDN.
Hope it can help.
If you want to bind the command (as #nmclean explains) from code, you can use:
CommandBindings.Add(new CommandBinding(
ApplicationCommands.Copy,
(sender, args) => { /* logic here */ }));

Runtime control population using XML in winform application

A thought came in mind, is there any way to populate control in runtime using XML. I mean I will have one Controls.xml file and in that file I can define what control i want to add to a perticular winform and when we run that app it will show exact controls. Has anyone done this? Please guide me on this.
Yes, you can create the controls dynamically: all you need to do is to parse the XML and then create them.
TextBox tb = new TextBox();
tb.Location = new Point(25,25);
tb.Click += textbox_Click;
this.Controls.Add (tb);
You can Serialize a Control (which is an Object) to XML than Deserialize se HOW TO
But the issue would be Event's ,where you should use Reflection and/or Code Injection into the Application because Event's cannot get Deserialized as an Object.

How to set Control Template in code?

I have this in XAML
<ControlTemplate TargetType="{x:Type Button}">
<Image ...>
</ControlTemplate>
I want to achieve same in C# code. How can I achieve this?
ControlTemplate ct = new ControlTemplate();..
Image img = new Image();..
Now how to assign this Image to Control template? Can we do this or Am I missing any concept here?
Creating template in codebehind is not a good idea, in theory one would do this by defining the ControlTemplate.VisualTree which is a FrameworkElementFactory.
ControlTemplate template = new ControlTemplate(typeof(Button));
var image = new FrameworkElementFactory(typeof(Image));
template.VisualTree = image;
Assigning properties is very roundabout since you need to use SetValue and SetBinding:
image.SetValue(Image.SourceProperty, ...);
Also, about the (previously) accepted answer and the stuff quoted:
Setting the ControlTemplate
programmatically is just like using
XAML because we have to use the
XamlReader class.
That statement is just wrong, we do not "have to".
If i assign templates at run time i define them as a resource which i can load if i need it.
Edit: According to the documentation FrameworkElementFactory is deprecated:
This class is a deprecated way to programmatically create templates, which are subclasses of FrameworkTemplate such as ControlTemplate or DataTemplate; not all of the template functionality is available when you create a template using this class. The recommended way to programmatically create a template is to load XAML from a string or a memory stream using the Load method of the XamlReader class.
I wonder if this recommendation is such a good idea. Personally i would still go with defining the template as a resource in XAML if i can avoid doing it with strings and the XamlReader.
http://www.eggheadcafe.com/sample-code/SilverlightWPFandXAML/73fdb6a2-6044-4c43-8766-afa12618ddc1/set-controltemplate-programmatically.aspx
Setting the ControlTemplate
programmatically is just like using
XAML because we have to use the
XamlReader class. For example, here is
the code to set a button's template,
assuming that we want to set a
button's template after it is loaded.
private void Button_Loaded(object sender, RoutedEventArgs e) {
var button = sender as Button;
string template =
"<ControlTemplate xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'
TargetType=\"Button\">" +
"<Border>" +
"<ContentPresenter/>" +
"</Border>" +
"</ControlTemplate>";
button.Template = (ControlTemplate)XamlReader.Parse(template);
}
Since we used a string for specifying
the XAML code for the template, we can
use the XamlReader's Parse method. The
XamlReader also has a Load method,
which is primarily used for streams or
XAML or XML readers. Notice that we
have to include the XML namespace
http://schemas.microsoft.com/winfx/2006/xaml/presentation
because the ControlTemplate, Border,
and other controls we need are defined
there. If we did not include it, we'll
encounter a runtime exception.
Basically, we have to put the
namespaces needed by the template.
If you need to change the button image only then you can do one thing.
Create a dependency property which will represent when you want to
change the image (a bool) or may be you can create an enum which has
all possible images say
Enum Images { Image1 = 0, Image2 = 1, Image2 = 3}. Create a dependency property "CurrentButtonImage" of this type which will be associated with button.
Now in XAML use this in button template
On property Change of CurrentButtonImage update the image of button (in code behind) using
CurrentImagePropertyChangedhandler(....,...)
{
switch(CurrentButtonImage)
{
case "Image1" :
this._ButtonImage.Fill = (DrawingBrush)csd.FindResource("Image1DrawingBrush");
break;
}
}

A simple C# question I hope! Add additional properties to Buttons

hi
on a windows form (not WPF) I dynamically create buttons on a flowlayout and I would like to add some properties to them simply to store other values (int and string) with the buttons for latter use.
Button bn = new Button();
bn.Text = "mybutton";
bn.Name = "mybutton";
toolTip1.SetToolTip(bn, "some tip");
bn.Location = new Point(200, 200);
bn.Size = new Size(110, 30);
bn.BackColor = SystemColors.Control;
bn.Show();
flowLayoutPanel1.Controls.Add(bn);
I have about 6 values I would like to store with each button as it is different for each button..
Can this be done?
For non-strongly-typed information, you can possibly use the Tag property. Otherwise, I think you'd have to subclass.
Derive from Button:
public class MyButton : Button
{
public string ExtraProperty {get;set;}
}
Personally, I think this is bad code. Really bad code.
Yes. You can assign data like this to the Button.Tag property (inherited from Control). This property is typed as an object so you can assign anything you want to it.
Alternative, you could inherit from Button.
Like all WinForms controls, Button also has a Tag property, which can be used to store arbitrary objects.
public struct MyButtonData {
public int myInt;
public string myString;
}
...
bn.Tag = new MyButtonData() {myInt = 3, myString = "Hello World"};
...
var data = (MyButtonData)bn.Tag;
You can either:
Create a control, derived from Button, and add the additional properties.
Create a class to encapsulate the data you want to assign to the each button, instantiate the class, and then point the control's "Tag" property at the instantiated object.
The Tag property was designed for this very purpose.
Something you would like to do in this case would be to create a custom control. With a custom control, you have more freedom than with the standard control. Not only will you inherit all the functionality from the existing control you are building your custom control on. You will also have the opportunity to add more functionality and properties to your custom control.
Source: Microsoft - Devloper Network.
https://msdn.microsoft.com/en-us/library/ff723977(v=expression.40).aspx

Categories

Resources