musium
musium

Reputation: 3072

using wpf from powershell

I’ve started playing around with powershell. At the moment I’m trying to load a C# class which displays a WPF window, so for so good. A TextBlock placed in the window binds to a Property in the class. (I’ve tested the binding in a CmdLine Application and it works fine)… but when I load the class from powershell using add-tape the binding won’t work.

What am I doing wrong?

$a =@"
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;

public class TestClass : INotifyPropertyChanged
    {
        private bool _showed = false;
        private String _myString;

        public String MyString
        {
            get { return _myString; }
            set
            {
                _myString = value;
                if (!_showed)
                    ThreadStuff();
                OnPropertyChanged("MyString");
            }
        }

        public TestClass()
        {
        }

        public TestClass(String value)
        {
            _myString = value;
        }

        private void ThreadStuff()
        {
            _showed = true;
            var thread = new Thread(new ThreadStart(() =>
            {
                CreateWindow();
                System.Windows.Threading.Dispatcher.Run();
            }))
            {
                IsBackground = true
            };
            thread.SetApartmentState(ApartmentState.STA);
            thread.Start();
        }

        private void CreateWindow()
        {
            var w = new Window();
            var g = new Grid();
            g.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) });
            g.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) });
            g.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
            g.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });

            for (int i = 0; i < g.RowDefinitions.Count; i++)
            {
                for (int j = 0; j < g.ColumnDefinitions.Count; j++)
                {
                    var b = new Button { Content = new TextBlock { Text = i.ToString() } };
                    Grid.SetRow(b, i);
                    Grid.SetColumn(b, j);
                    g.Children.Add(b);
                }
            }

            var t = new TextBlock();
            var binding = new Binding { Source = MyString, Mode = BindingMode.OneWay };
            t.SetBinding(TextBlock.TextProperty, binding);

            (g.Children[g.Children.Count - 1] as Button).Content = t;

            w.Content = g;
            w.Show();
        }

        public event PropertyChangedEventHandler PropertyChanged;
        protected virtual void OnPropertyChanged(string propertyName)
        {
            var handler = PropertyChanged;
            if (handler != null)
                handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
"@

Add-Type -TypeDefinition $a -ReferencedAssemblies presentationcore, presentationframework, windowsbase, "System.Xaml"

$test = New-Object TestClass
$test.MyString = 'hi from powershell'

Btw. I’m working with powershell for the first time (I’ve just worked with C# until now ). In the end it is my goal to load a Xaml file as view and a C# file as view mode, put them together and set the property of the vm from powershell (Yes it is totally stupide and it would be much easier to write a normal WPF application… but I’ve to do it this way…school now a days^^ )

Upvotes: 0

Views: 950

Answers (1)

latkin
latkin

Reputation: 16792

What version of powershell are you using? Your code "works" for me in Powershell 3.0 on Win8.

I say "works" because it works the same as when I run it via a C# console application:

  • Nothing happens until you set MyString
  • First time you set MyString, a GUI pops up, and lower right quadrant contains the value of MyString
  • Nothing happens on subsequent modifications of MyString (The binding is not set up correctly, so the text won't update when you update MyString)

If this is your desired behavior, and it's not working AT ALL, then it might be an issue with older versions of PS.

I suspect your real issue is that the binding isn't working. That's because this line:

var binding = new Binding { Source = MyString, Mode = BindingMode.OneWay };

should be

var binding = new Binding { Source = this, Mode = BindingMode.OneWay, Path = new PropertyPath("MyString") };

Making that change, everything seems hooked up just fine in both C# console app and powershell.

Upvotes: 1

Related Questions