Reputation: 3072
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
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:
MyString
MyString
, a GUI pops up, and lower right quadrant contains the value of MyString
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