Однажды мне потребовалось открыть окно из консольного приложения. Я хотел это сделать используя wpf, но информации, разбросанной по сети оказалось мало, так что я решил как-то систематизировать и представить этот маленький туториал.
Созадем обычное консольное приложение на .net framework.
Теперь необходимо добавить зависимости: WindowsBase, PresentationCore, PresentationFramework.
Добавим класс нашего окна, унаследовав его от стандартных окон винды.
Добавим методу main атрибут [STAThread]
Теперь создадим наше окно:
Если мы теперь вызовем на окне метод Show(), оно тут же схлопнется, а так как нам бы хотелось на него смотреть все время, то это окно нужно запихнуть в контейнер, который поддерживает весь жизненный цикл.
Мы отобразили окно, и оно неплохо себя чувствует, но закрыть его из кода так просто не получится: метод Run() — являет из себя бесконечный цикл, а остановить Application можно только из того же потока, где он вызван. Выход:
Тогда весь метод выглядит
Приятным решением будет не составлять наше окно из кода, а перейти к более привычному xaml.
Для этого добавляем зависимость System.Xml.
И составляем xaml документ.
Теперь загружаем данные из файла.
И в таком варианте конечный Main выглядит
P.S.
Спасибо с# чату в тг и пользователю Юрий.
Созадем обычное консольное приложение на .net framework.
Теперь необходимо добавить зависимости: WindowsBase, PresentationCore, PresentationFramework.
Добавим класс нашего окна, унаследовав его от стандартных окон винды.
public class MyWindow : Window{}
Добавим методу main атрибут [STAThread]
Зачем
STAThreadAttribute по существу является обязательным требованием для обмена сообщениями с сервером сообщений Windows с компонентами COM
А подробнее.
А подробнее.
[STAThread]
public static void Main(string[] args){}
Теперь создадим наше окно:
[STAThread]
public static void Main(string[] args)
{
var win = new MyWindow { Width = 350, Height = 350};
var grid = new Grid();
var text = new TextBox {Text = "my text"};
grid.Children.Add(text);
win.Content = grid;
}
Если мы теперь вызовем на окне метод Show(), оно тут же схлопнется, а так как нам бы хотелось на него смотреть все время, то это окно нужно запихнуть в контейнер, который поддерживает весь жизненный цикл.
app.MainWindow = win;
app.MainWindow.Show();
app.Run();
Мы отобразили окно, и оно неплохо себя чувствует, но закрыть его из кода так просто не получится: метод Run() — являет из себя бесконечный цикл, а остановить Application можно только из того же потока, где он вызван. Выход:
Task.Run(async () =>
{
await Task.Delay(1000);
app.Dispatcher.Invoke((Action) delegate { app.Shutdown(); });
});
;
Тогда весь метод выглядит
так.
а тут исходник
[STAThread]
public static void Main(string[] args)
{
var app = new Application();
var win = new MyWindow { Width = 350, Height = 350};
var grid = new Grid();
var text = new TextBox {Text = "my text"};
grid.Children.Add(text);
win.Content = grid;
app.MainWindow = win;
app.MainWindow.Show();
Task.Run(async () =>
{
await Task.Delay(1000);
app.Dispatcher.Invoke((Action) delegate { app.Shutdown(); });
});
app.Run();
}
а тут исходник
Приятным решением будет не составлять наше окно из кода, а перейти к более привычному xaml.
Для этого добавляем зависимость System.Xml.
И составляем xaml документ.
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:ConsoleApplication1"
mc:Ignorable="d"
Title="MyWindow" Height="450" Width="800">
<Grid>
<Label Content="Label" />
</Grid>
</Window>
Теперь загружаем данные из файла.
XmlTextReader r = new XmlTextReader("MyWin.xaml");
var win = XamlReader.Load(r) as Window;
И в таком варианте конечный Main выглядит
так.
[STAThread]
public static void Main(string[] args)
{
var app = new Application();
XmlTextReader r = new XmlTextReader("MyWin.xaml");
var win = XamlReader.Load(r) as Window;
app.MainWindow = win;
app.MainWindow.Show();
Task.Run(async () =>
{
await Task.Delay(1000);
app.Dispatcher.Invoke((Action) delegate { app.Shutdown(); });
});
app.Run();
}
P.S.
Спасибо с# чату в тг и пользователю Юрий.