0

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^^ )

4

1 回答 1

1

你用的是什么版本的powershell?您的代码在 Win8 上的 Powershell 3.0 中为我“工作”。

我说“工作”是因为它的工作方式与我通过 C# 控制台应用程序运行它时的工作方式相同:

  • 在你设置之前什么都不会发生MyString
  • 第一次设置时MyString,会弹出一个GUI,右下象限包含值MyString
  • MyString(绑定未正确设置,因此更新时文本不会更新MyString)的后续修改没有任何反应

如果这是您想要的行为,并且它根本不起作用,那么它可能是旧版本 PS 的问题。

我怀疑您的真正问题是绑定不起作用。那是因为这一行:

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

应该

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

进行这种更改后,C# 控制台应用程序和 powershell 中的一切似乎都很好。

于 2013-02-20T21:28:33.400 回答