-1

I want to get a XAML specified interface on the screen so I can learn WPF. But I do not want to start from a visual studio project which has all the wire-up already done. I wan't the c# "hello world" equavalent of drawing a window specified in a xaml file on the screen from the "main()" function.

So how do I wire-up a XAML file to an object and draw it on the screen from a console app ? Please wire-up a simple event as well. Say a "hello world" button (specified in xaml), that when pressed makes the console print "hello world". I'd prefer to see the delegate function in the following ways.

  1. The logic as inline c# in XAML.
  2. The logic specified in the same file as the "main()" method, as a free function (edit : oh wait c# doesn't have free functions, well a delegate of some sort that isn't code behind).
  3. The logic as a member function of an object, where I believe the object to be the codebehind of the XAML (assuming ofcourse this way of mapping between xaml and c# objects is possible).

Additionally : This answer shows the ui runloop taking over the main thread, is there any sugar to create a new thread for the app so it doesn't block the callee ?

If your wondering why I am asking this question, or why I want to learn WPF this way. I want to trigger ad-hoc UI elements from within a plugin that has no other means of displaying information.


For those that find this question too vague, here is an example of xaml

<Canvas xmlns="http://schemas.microsoft.com/client/2007"  
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <TextBlock>Hello World!</TextBlock>
</Canvas>

The main app in this question is a console c# app, the XAML file represents a form with a single button, pressing the button prints "hello world" to the console. And I want to see the different ways of wiring up the button to my code, I do not understand how I could be clearer.

Community
  • 1
  • 1
Hassan Syed
  • 20,075
  • 11
  • 87
  • 171
  • 1
    Hard to tell what is being asked here. Do you want to rewrite the WPF codebase for creating and drawing a window? This sounds like an incredibly complex and unnecessary task. Or are you just trying to display a `Window` from a console application? If so then slugster's answer is correct. – Alex Wiese Dec 05 '12 at 02:35
  • I need to specify and layout a UI form specified in XAML, create a window object that lays itself out from the XAML file, and then see how the UI elements wire up to the delegates. Here is an examle of XAML Layout ... http://code.google.com/p/wpf-mvvm-calculator/source/browse/trunk/Calculator/Views/CalculatorView.xaml?r=2 – Hassan Syed Dec 05 '12 at 02:39
  • Ok... makes more sense, in that case the XamlReader is the way to go, i'll show you what we use to load UI from XAML in the database – TimothyP Dec 05 '12 at 02:41
  • OK so you want to load XAML at runtime and display the `Window`. You can use a `XAMLReader` then call `Window.Show()` http://msdn.microsoft.com/en-us/library/system.windows.markup.xamlreader.aspx – Alex Wiese Dec 05 '12 at 02:42
  • Ok, thanks. I'll look through the msdn article and come back and answer once I have it figured out. – Hassan Syed Dec 05 '12 at 02:48
  • 1
    So..... clearly your question wasn't clear to begin with.... you might want to go and delete some of your comments that you left ;) – slugster Dec 05 '12 at 02:50
  • No, you did not want to comprehend my question, I got 2 favourites before you answered, so clearly some people out there understood the question. – Hassan Syed Dec 05 '12 at 02:55
  • I only made this a favorite because I wanted updates so I could find out what the question meant. – Alex Wiese Dec 05 '12 at 03:29

2 Answers2

4

At the risk of being told this is not what you asked, but since it's not clear:

class WpfSample
{
    [STAThread]
    public static void Main()
    {
        var window = new Window()
        {
            Title = "WPF",
            Width = 640,
            Height = 480
        };

        var grid = new Grid();

        var button = new Button()
        {
            Content = "Click Me",
            Width = 100,
            Height = 50,

        };

        grid.Children.Add(button);
        window.Content = grid;

        button.Click += (s, e) =>
        {
            MessageBox.Show("You clicked me");
        };

        window.ShowDialog();

    }
}

That being said, if you want plugins for your WPF application, doing it like this (all with code) is not the way to go.

We define controls en such in plugins without the need for hooking it all up in code, we use MEF for that.

Update To load the UI from some XAML you stored somewhere, you can use a ValueConverter

public class StringToXamlValueConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        string xaml;
        if (value != null && !String.IsNullOrWhiteSpace(value.ToString))
        {
            xaml = value.ToString();
        }
        else
        {
            xaml = Settings.Default.DefaultLayoutView;
        }

        var root = XamlReader.Parse(xaml);
        return root;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

You'd then set the content of some element like this:

<ContentControl Content="{Binding Layout.View, Converter={StaticResource StringToXamlConverter}}"/>
TimothyP
  • 21,178
  • 26
  • 94
  • 142
  • 1
    +1. Here is a blog post of mine showing how to do this from a resource file: [Dynamic ControlTemplate in Silverlight](http://techfilth.blogspot.co.nz/2010/01/dynamic-controltemplate-in-silverlight.html). (It's Silverlight, but you can still do it in WPF). – slugster Dec 05 '12 at 02:48
  • I'm not trying to create plugins for a WPF app, I am writing a plugin to a networking service that has no GUI or no suitable means to get data onto the screen for debugging and monitoring during development. So, I want to be able to pop up a window at will from within a headless app and interact with the service. – Hassan Syed Dec 05 '12 at 02:53
  • Does that app come with the ability to load plugins, do you have the source for that app? For either of those situations, have you considered alternatives for getting the data out? For example a plugin that uses NLog to log to a syslog and a UI that gets data from there. ie. let the plugin push data somewhere and pull it with a UI app. Keep the concerns separated There are many ways to solve it – TimothyP Dec 05 '12 at 02:57
  • Ok the answer is almost there, could you show how I would wire up a delegate to the XAML passed in as a string ? So the XAML passed in will have a button, I want the delegate wire to the "onPressed" event :D – Hassan Syed Dec 05 '12 at 02:58
  • If the default logging stuff is not enough, you could even push out serialized instances of the objects in the service to a rabbitmq server and then fetch them with a UI app from there (it's as good as realtime) You could then visualize them any way you want – TimothyP Dec 05 '12 at 02:58
  • I'd use Commands for that, for example the RelayCommand in MVVMLight. The xaml would contains a button The Command is defined on the ViewModel and will be executed when the button is clicked. This keeps the UI disconnected from the actuall code, allowing you to swap in new user interfaces without having to deal with event handlers and other hookups. Does that make sense? – TimothyP Dec 05 '12 at 03:01
  • I have the source of the app, and the GUI is only for development or monitoring, I don't want to overcomplicate things by sticking in middleware. I simple want to know how to do a use-case, not the merits of different approaches that belong to the big picture, that would be another question in it's own right. I mean if someone comes and asks "how can I chop down a tree, I wan't to learn how to make a chair", would you tell him to go to IKEA instead ? I'm sure if he was only interested in acquiring a chair, he would probably ask "where could I buy a chair ?". – Hassan Syed Dec 05 '12 at 03:02
  • If the logic for the delegate is contained in the UI plugin, you simply create your UI the normal way with code behind and have your service create an instance of that. If the logic is defined by the service you have the service pass the delegate (or Action) to the plugin and have the plugin execute that when the button is clicked – TimothyP Dec 05 '12 at 03:08
1

To cut straight to the point:

I want to trigger ad-hoc UI elements from within a plugin that has no other means of displaying information.

There is absolutely no need to draw a window from scratch, instead you can use the ShowDialog() method on the Window object:

var myWindow = new Window();
myWindow.ShowDialog();

of course you can programmatically add whatever controls you want to that window, or you could have it already defined as XAML somewhere which you then re-hydrate as a window.

Having said that, ideally the host of your plugin should provide you with a container that you can add content to (or provide a dialog service that you've hand rolled), rather then you having to forcibly show stuff directly from the plugin.

slugster
  • 49,403
  • 14
  • 95
  • 145
  • that doesn't answer my question.... and the information is realtime streaming data .... the question has merit on it's own, and the point at the end of the question was just trivia and has nothing to do with the question. Why do people go for trying to get in easy answers ? – Hassan Syed Dec 05 '12 at 02:28
  • @slugster I upvoted this as it didn't deserve the downvote. Hard to tell what he wants – Alex Wiese Dec 05 '12 at 02:32
  • 1
    @HassanSyed Then your question is either misguided or misleading. Are you showing graphical data that must be rendered to the screen as is? If not then my answer covers what you've asked for (I also edited it shortly after posting, make sure you've seen it). – slugster Dec 05 '12 at 02:32
  • 1
    He's obviously trying to reinvent the wheel – TimothyP Dec 05 '12 at 02:32
  • if I was trying to reinvent the wheel I'd roll my own UI toolkit. – Hassan Syed Dec 05 '12 at 02:32
  • 1
    Another way to load UI at runtime: http://msdn.microsoft.com/en-us/library/system.windows.markup.xamlreader.parse.aspx (we've used this for certain situations as well, where the UI is stored in a database) – TimothyP Dec 05 '12 at 02:39
  • 1
    @TimothyP yep, that's what I was alluding to when I mentioned re-hydrating - the XAML could also be stored as a resource within the plugin. – slugster Dec 05 '12 at 02:43
  • @slugster I'm quite irritated, you did not allude anything, you sidestepped my question in an attempt to score an answer, your supposed to use the comments for that.... +1 timothy. – Hassan Syed Dec 05 '12 at 02:47
  • 1
    @HassanSyed You are lucky anyone took a punt on answering the original version of your question. To quote my answer: *or you could have it already defined as XAML somewhere which you then `re-hydrate as a window.`* If you check the link to a blog post I left you will find that I do know what I'm talking about. I didn't answer your question exhaustively because it was unclear **except for your final point** (hence why I quoted it). My job as a tech lead is to cut through the BS and unclear information, not encourage it, and to answer the question with the info provided (which was minimal). – slugster Dec 05 '12 at 03:11
  • I don't see any ShowDialog() method in Windows::UI::Xaml::Window class. Its a pity cause I'd love to have it (C++). – Aidan Oct 15 '13 at 17:21