Можно ли сделать что-то похожее на XAML в C# (WPF)? Отделить UI от кода?
На самом деле можно, это называется Ресурсы диалоговых окон. Несмотря на название, их область использования куда шире, чем диалоговые окна в традиционном смысле. Например, ничто не мешает:
Сделать главное окно приложение диалоговым, если оно состоит исключительно из элементов управления и не содержит сложной логики отрисовки.
Создать диалоговое окно со стилем WS_CHILD и вкладывать его в другие окна (аналог User Control).
Пример. Нарисуем с помощью редактора ресурсов Visual Studio такое диалоговое окно:
Редактор ресурсов не содержится в студии Express-версий, поэтому при их использовании нужно будет найти сторонний редактор или редактировать определения ресурсов вручную (см. ниже).
В результате получим файл ресурсов и заголовочный файл. Откроем их в текстовом редакторе и удалим лишний текст, сгенерированный IDE, получим в результате:
Resource.h (идентификаторы элементов управления, используются для связи кода с UI)
#define IDD_CALC 103
#define IDC_INPUT1 1000
#define IDC_INPUT2 1001
#define IDC_PLUS 1002
#define IDC_MINUS 1003
#define IDC_MULTI 1004
#define IDC_DIV 1005
Resource.rc (определение UI, аналог XAML)
#include "resource.h"
#include "windows.h"
LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_CALC DIALOGEX 0, 0, 217, 89
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Супер калькулятор"
FONT 8, "MS Shell Dlg", 0, 0, 0x1
BEGIN
DEFPUSHBUTTON "Выход",IDOK,160,68,50,14,WS_GROUP
EDITTEXT IDC_INPUT1,15,14,47,15,ES_AUTOHSCROLL | ES_NUMBER
EDITTEXT IDC_INPUT2,15,36,47,15,ES_AUTOHSCROLL | ES_NUMBER
PUSHBUTTON "+",IDC_PLUS,77,15,18,12
PUSHBUTTON "-",IDC_MINUS,105,15,18,12
PUSHBUTTON "*",IDC_MULTI,77,36,18,12
PUSHBUTTON "/",IDC_DIV,105,36,18,12
END
Далее добавим код:
Model.cpp
#include <windows.h>
#include "resource.h"
//Логика вычислений
BOOL Calculate(UINT idAction, int arg1, int arg2, int* pOutput) {
if (pOutput == NULL) return FALSE;
if (idAction == IDC_DIV && arg2 == 0) return FALSE;
switch (idAction) {
case IDC_PLUS: *pOutput = arg1 + arg2; return TRUE;
case IDC_MINUS: *pOutput = arg1 - arg2; return TRUE;
case IDC_MULTI: *pOutput = arg1 * arg2; return TRUE;
case IDC_DIV: *pOutput = arg1 / arg2; return TRUE;
}
return FALSE;
}
ViewModel.cpp
#include <windows.h>
#include <stdlib.h>
#include <tchar.h>
#include "resource.h"
//объявления функций
BOOL InitInstance(HINSTANCE, int);
INT_PTR CALLBACK DlgCalc_Callback(HWND, UINT, WPARAM, LPARAM);
BOOL Calculate(UINT idAction, int arg1, int arg2, int* pOutput);
// Глобальные переменные
HINSTANCE hInst;
HWND hWnd = NULL;
// Точка входа
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// Выполнить инициализацию приложения
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
MSG msg;
// Цикл основного сообщения
while (GetMessage(&msg, nullptr, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int) msg.wParam;
}
//Инициализация приложения
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance;
//создать окно
CreateDialog(hInstance, MAKEINTRESOURCE(IDD_CALC), NULL, DlgCalc_Callback);
if (!hWnd)
{
return FALSE;
}
//отобразить окно
ShowWindow(hWnd, nCmdShow);
return TRUE;
}
//Логика обработки команд в окне
INT_PTR ProcessCommand(HWND hDlg, UINT idAction) {
BOOL success = FALSE;
int x, y, res;
if (idAction == IDOK || idAction == IDCANCEL)
{
//закрыть окно
DestroyWindow(hDlg);
return (INT_PTR)TRUE;
}
if (idAction >= IDC_PLUS && idAction <= IDC_DIV) {
//получение входных данных
x = GetDlgItemInt(hDlg, IDC_INPUT1, &success, TRUE);
if (success == FALSE) {
MessageBox(hDlg, L"Введенное число некорректно", NULL, MB_OK | MB_ICONERROR);
return (INT_PTR)TRUE;
}
y = GetDlgItemInt(hDlg, IDC_INPUT2, &success, TRUE);
if (success == FALSE) {
MessageBox(hDlg, L"Введенное число некорректно", NULL, MB_OK | MB_ICONERROR);
return (INT_PTR)TRUE;
}
//выполнение команды
success = Calculate(idAction, x, y, &res);
if (success == FALSE) {
MessageBox(hDlg, L"При вычислении произошла ошибка", NULL, MB_OK | MB_ICONERROR);
return (INT_PTR)TRUE;
}
//вывод результата
SetDlgItemText(hDlg, IDC_INPUT2, L"");
SetDlgItemInt(hDlg, IDC_INPUT1, res, TRUE);
return (INT_PTR)TRUE;
}
return (INT_PTR)FALSE;
}
INT_PTR CALLBACK DlgCalc_Callback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
UINT idAction;
switch (message)
{
case WM_INITDIALOG:
hWnd = hDlg;
return (INT_PTR)TRUE;
case WM_COMMAND:
idAction = LOWORD(wParam);
return ProcessCommand(hDlg, idAction);
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return (INT_PTR)FALSE;
}
В итоге получаем приложение с разделением на декларативное определение UI, логику UI и логику вычислений, хотя по возможностям это и далеко от WPF/XAML.
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Мне необходимо считать из файла данные в двоичном виде - сначала несколько int, потом uint8_t, затем еще кое-что
Раньше в netbeans терминал Cygwin работал даже без открытия java проекта, но теперь после обновления пишет сообщение "unable to start pty process": Прошу тока не предлагать...
Хочу использовать Xalan-J для XSLT-преобразования (Java 8)Скачал библиотеку Xalan-J 2
У меня recyclerView с кучей элементов, каждый элемент должен отформатировать и отобразить Date, паттерн для всех одинаковый