Форум программистов, компьютерный форум, киберфорум
C#: WPF, UWP и Silverlight
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.65/20: Рейтинг темы: голосов - 20, средняя оценка - 4.65
 Аватар для firnen_dragon
25 / 25 / 4
Регистрация: 21.01.2019
Сообщений: 407

Вывод на печать изображения MVVM

09.02.2024, 15:47. Показов 5131. Ответов 69

Студворк — интернет-сервис помощи студентам
Есть у меня в модели такой вот простой метод:
C#
1
2
3
4
5
6
7
8
9
10
public void PrintingQR() 
{
    PrintDialog dlg = new PrintDialog();
    bool? result = dlg.ShowDialog();
 
    if (result.HasValue && result.Value)
    {
        dlg.PrintVisual(qrImage, "Печать картинки");
    }
}
Как я понял PrintDialog не может принимать ни Bitmap ни ImageBitmap, он принимает сами визуальные элементы, а мне нужно распечатать картинку, которая биндится к Image во View, отсюда вопрос, как мне в модель Image прокинуть? Сервис для этого писать чтоб из списка элементов окна его вытаскивать типа этого?
C#
1
2
3
4
5
6
7
8
9
10
11
12
public Visual PrintingQR()
{
    Visual result = null;
    foreach (Window window in Application.Current.Windows)
    {
        if (window.GetType() == typeof(MainWindow))
        {
            result =(window as MainWindow).image;
        }
    }
    return result;
}
Других вариантов пока не придумал, но чую есть способ попроще и красивее, ну или другой вариант печати

Добавлено через 23 минуты
Не PrintDialog, а PrintVisual я имел ввиду...
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
09.02.2024, 15:47
Ответы с готовыми решениями:

Вывод изображения на печать
Подскажите как вывести картинку на печать, именно картинку, про xml, pdf и doc файлы в поиске по находил, а как вывести картинку на печать...

Вывод на печать изображения
Здраствуйте!:)Как можно при печати дать пользовател выбрать принтер и получить контекст принтера для этого принтера?Заранее всем спасибо!:)

Вывод изображения в отчёт на печать
Всем доброго времени суток. Загружаю картинку в базу и вывожу на форму вот так (брал из примеров): &НаКлиенте Процедура...

69
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16165 / 11285 / 2891
Регистрация: 21.04.2018
Сообщений: 33,174
Записей в блоге: 2
12.02.2024, 13:56
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от firnen_dragon Посмотреть сообщение
что мне нужно просто сервис написать для PrintDialog и OpenFileDialog, вызывать их в vm и тогда это будет приемлемо?
Диалоги - да.
А вот насколько нужно их их VM вызывать - это уже вопрос.
Я бы на уровне View всё оставил.

Цитата Сообщение от kotelok Посмотреть сообщение
В рамках MVVM есть два типа ограничений - технические (категорически не могут нарушаться) и идеологические (тут уже зависит от задачи, ну и вопрос весьма холиварный).
Скорее - концептуальные и рекомендуемые.

Цитата Сообщение от firnen_dragon Посмотреть сообщение
Я просто одного понять не могу View-слой - это где писать то? Я всегда думал, что к View относится XAML окон, кодбихайнд ну и сервисы, в кодбихайнде писать не желательно, остаются только сервисы и XAML,
View слой, кроме XAML и Code Behind, это ещё: конвертеры, селекторы стилей, шаблонов, Custom Control, расширения разметки, различный контейнеры и прокси (в том числе логаторы, шины сообщений и т.п.), хелперы (в том числе статические обработчики событий), навигаторы, источники данных (в том числе почти таже VM, но с логикой для UI) и ещё многое-многое другое.

Цитата Сообщение от xellan24rus Посмотреть сообщение
Но я так понимаю View это только xaml?
Категорически нет.

Добавлено через 28 секунд
Чтобы что-то использовать в XAML - это "что-то" нужно сначала написать на Шарпе.

Добавлено через 2 минуты
Чтобы что-то использовать в XAML - это "что-то" нужно сначала написать на Шарпе.
Цитата Сообщение от xellan24rus Посмотреть сообщение
А вот если в событиях mainwindow работа идет это относится к view, но нарушает mvvm.
Если в обработчике нет непосредственно обработки данных, то это не нарушает MVVM.
Например, в обработчике может быть вызов метода VM который возвращает какой-то результат (что невозможно для команды) и на этот результат представление по разному будет реагировать. Вот такой обработчик нечем не нарушает MVVM.

Добавлено через 1 минуту
Другое дело, что VM лучше стараться реализовывать так чтобы в подобном не было необходимости. Но это уже рекомендация, а не концептуальный запрет.
1
 Аватар для firnen_dragon
25 / 25 / 4
Регистрация: 21.01.2019
Сообщений: 407
12.02.2024, 14:02  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
View слой, кроме XAML и Code Behind, это ещё: конвертеры, селекторы стилей, шаблонов, Custom Control, расширения разметки, различный контейнеры и прокси (в том числе логаторы, шины сообщений и т.п.), хелперы (в том числе статические обработчики событий), навигаторы, источники данных (в том числе почти таже VM, но с логикой для UI) и ещё многое-многое другое.
А в где мне лучше всего печать Image тогда вызывать? В конвертере?
0
 Аватар для xellan24rus
364 / 296 / 55
Регистрация: 08.04.2020
Сообщений: 1,175
12.02.2024, 14:10
Элд Хасп, Информативно и подробно)
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16165 / 11285 / 2891
Регистрация: 21.04.2018
Сообщений: 33,174
Записей в блоге: 2
12.02.2024, 14:28
Цитата Сообщение от firnen_dragon Посмотреть сообщение
А в где мне лучше всего печать Image тогда вызывать? В конвертере?
Как я бы сделал.
Печать в WPF - это всегда печать какого-то Visual.
Соответственно нужно сделать кнопку со всплывающей командой ApplicationCommands.Print. Нацелить источник или параметр команды на нужный Visual (в данном случае ваш Image). В Окне отловить эту команду через CommandBinding в Execute которого задан статический обработчик из хелпера.

Добавлено через 2 минуты
Можно сделать контекстное меню для вашего Image с той же логикой.

Добавлено через 2 минуты
ApplicationCommands.Print можно заменить на статическую команду в хелпере, которая получит из параметра Visual и распечатает его.
1
 Аватар для firnen_dragon
25 / 25 / 4
Регистрация: 21.01.2019
Сообщений: 407
12.02.2024, 14:29  [ТС]
Элд Хасп, Спасибо, попробую разобраться как это сделать
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16165 / 11285 / 2891
Регистрация: 21.04.2018
Сообщений: 33,174
Записей в блоге: 2
12.02.2024, 14:37
Цитата Сообщение от firnen_dragon Посмотреть сообщение
попробую разобраться как это сделать
C#
1
2
3
4
5
6
7
public static class PrintHelper
{
    public static readonly ICommand Start = new RelayCommand<Visual>(visual =>
    {
          // Здесь распечатка параметра visual
    });
}
Добавлено через 1 минуту
Это в самом простом виде.
К нему можно добавить ещё различные "навороты". В первую очередь, советую добавить расширение разметки.
1
 Аватар для firnen_dragon
25 / 25 / 4
Регистрация: 21.01.2019
Сообщений: 407
12.02.2024, 15:26  [ТС]
Элд Хасп, Поскажите пожалуйста где найти реализацию RelayCommand с аргументами типа, я использую вашу, но только эту:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class RelayCommand : ICommand
{
    private readonly Func<object, bool> _canExecute;
    private readonly Action<object> _onExecute;
 
    /// <summary>Событие извещающее об измении состояния команды</summary>
    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }
 
    /// <summary>Конструктор команды</summary>
    /// <param name="execute">Выполняемый метод команды</param>
    /// <param name="canExecute">Метод разрешающий выполнение команды</param>
    public RelayCommand(Action<object> execute, Func<object, bool> canExecute = null)
    {
        _onExecute = execute;
        _canExecute = canExecute;
    }
 
    /// <summary>Вызов разрешающего метода команды</summary>
    /// <param name="parameter">Параметр команды</param>
    /// <returns>True - если выполнение команды разрешено</returns>
    public bool CanExecute(object parameter) => _canExecute == null ? true : _canExecute.Invoke(parameter);
 
    /// <summary>Вызов выполняющего метода команды</summary>
    /// <param name="parameter">Параметр команды</param>
    public void Execute(object parameter) => _onExecute?.Invoke(parameter);
}
Добавлено через 1 минуту
И еще вот вопрос как указать визуальный элемент в качестве источника?
XML
1
<Button Content="Сохранить картинкой" Margin="10" Grid.Column="0" Command="{Binding ApplicationCommands.Print,Source= {StaticResource image}}">
0
 Аватар для xellan24rus
364 / 296 / 55
Регистрация: 08.04.2020
Сообщений: 1,175
12.02.2024, 15:45
firnen_dragon, что такое аргументы в этом случае?
XML
1
<Button Content="Сохранить картинкой" Margin="10" Grid.Column="0" Command="{Binding ApplicationCommands.Print}" CommandParameter="{StaticResource image}" />
И в c# приводите object к нужному типу
C#
1
2
3
4
5
 public void Print(object parameter)
    {
                  Image image = parameter as Image;
 
    }
Добавлено через 45 секунд
Параметры команды передаете как CommandParameter, это может быть хоть что.
1
 Аватар для firnen_dragon
25 / 25 / 4
Регистрация: 21.01.2019
Сообщений: 407
12.02.2024, 16:18  [ТС]
xellan24rus, Похоже я вопрос неправильно сформулировал. У меня Image просто в Xaml окна находится(не в ресурсах), там нет x:Key, в этом случае что мне нужно сделать чтобы я мог задать его как ресурс в кнопке?
И я не до конца понимаю как мне забиндить в CommandBindings Execute тоже, по моему я какую-то фигню понаписал:
XML
1
2
3
4
5
<Image x:Name="image" Margin="10" Source="{Binding QrImage, Mode=OneWay}"/>
<Button Content="Сохранить картинкой" Margin="10" Grid.Column="0" Command = "{Binding ApplicationCommands.Print}" CommandParameter="{StaticResource image}">
    <Button.CommandBindings>
        <CommandBinding Command="Print" Executed="{helpers:PrintHelper.Start}"/>
    </Button.CommandBindings>
C#
1
2
3
4
5
6
7
8
9
public static class PrintHelper
{
    public static readonly ICommand Start = new RelayCommand(Print);
    public static void Print(object parameter)
    {
        Image image = parameter as Image;
 
    }
}
0
 Аватар для xellan24rus
364 / 296 / 55
Регистрация: 08.04.2020
Сообщений: 1,175
12.02.2024, 16:30
firnen_dragon, понял, не заметил что вы используете

XML
1
<Button Content="Сохранить картинкой" Margin="10" Grid.Column="0" Command="{x:Static PrintHelper.Start}" CommandParameter="{Binding ElementName=image}"></Button>
Попробуйте это

Добавлено через 27 секунд
Должно получиться, отпишите результат)

Добавлено через 2 минуты
XML
1
<Button Content="Print" Command="{x:Static local:PrintHelper.Start}" CommandParameter="{Binding ElementName=image}" />
Или вот так, где
XML
1
 xmlns:local="clr-namespace:YourNamespace"
1
 Аватар для firnen_dragon
25 / 25 / 4
Регистрация: 21.01.2019
Сообщений: 407
12.02.2024, 16:37  [ТС]
Цитата Сообщение от xellan24rus Посмотреть сообщение
отпишите результат
Спасибо, в Print заходит, но передаваемый параметр всегда null, дже если картинка есть в Image

Добавлено через 2 минуты
Все работает если так ElementName=image
0
 Аватар для xellan24rus
364 / 296 / 55
Регистрация: 08.04.2020
Сообщений: 1,175
12.02.2024, 16:40
firnen_dragon, понял, хорошо что разобрались)))
1
 Аватар для firnen_dragon
25 / 25 / 4
Регистрация: 21.01.2019
Сообщений: 407
12.02.2024, 16:41  [ТС]
xellan24rus, Спасибо большое
1
 Аватар для xellan24rus
364 / 296 / 55
Регистрация: 08.04.2020
Сообщений: 1,175
12.02.2024, 16:44
Цитата Сообщение от firnen_dragon Посмотреть сообщение
Спасибо большое
Ну основной код дал Элд Хасп, я только помог с привязкой и заодно узнал что параметром можно и элемент целиком передать, я так не делал раньше
2
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16165 / 11285 / 2891
Регистрация: 21.04.2018
Сообщений: 33,174
Записей в блоге: 2
12.02.2024, 17:31
Цитата Сообщение от firnen_dragon Посмотреть сообщение
Поскажите пожалуйста где найти реализацию RelayCommand с аргументами типа, я использую вашу, но только эту:
Простые реализации для тем на форуме

Добавлено через 31 секунду
Класс RelayCommand<T>

Добавлено через 1 минуту
Цитата Сообщение от firnen_dragon Посмотреть сообщение
И еще вот вопрос как указать визуальный элемент в качестве источника?
Если для обычной команды, то только в CommandParameter.
Если для RoutedCommand, то ещё и в CommandTarget.

Добавлено через 1 минуту
Цитата Сообщение от xellan24rus Посмотреть сообщение
И в c# приводите object к нужному типу
Команда с типизацией всё же удобнее в использовании.

Добавлено через 1 минуту
Цитата Сообщение от firnen_dragon Посмотреть сообщение
public static readonly ICommand Start = new RelayCommand(Print);
C#
1
2
3
4
5
6
7
8
9
public static class PrintHelper
{
    public static readonly ICommand Start = new RelayCommand<Visual>(Print); 
    public static void Print(Visual visual)
    {
        // Some Code
 
    }
}
1
 Аватар для firnen_dragon
25 / 25 / 4
Регистрация: 21.01.2019
Сообщений: 407
12.02.2024, 18:15  [ТС]
Элд Хасп, Спасибо)

Добавлено через 32 минуты
Элд Хасп, Последний вопросик спрошу, а если у менят 2 режима печати, в зависимости от режима будут меняться размеры картинки, а какой сейчас режим я могу понять только проверив свойство в VM, получается появляется смыл вызывать сервис печати из VM?
XML
1
2
3
4
5
6
<ComboBox Margin="10,5,10,10" Text="Режим" Height="22" SelectedItem="{Binding SelectedMode}">
    <ComboBox.Items>
        <ComboBoxItem Content="нормальный"/>
        <ComboBoxItem Content="процесс"/>
    </ComboBox.Items>
</ComboBox>
C#
1
2
3
4
5
public ComboBoxItem SelectedMode
{
    get => selectedMode;
    set => Set(ref selectedMode, value);
}
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16165 / 11285 / 2891
Регистрация: 21.04.2018
Сообщений: 33,174
Записей в блоге: 2
12.02.2024, 18:50
Цитата Сообщение от firnen_dragon Посмотреть сообщение
а какой сейчас режим я могу понять только проверив свойство в VM, получается появляется смыл запускать печать командой из VM?
Неа...
Здесь лучше подойдёт RoutedCommand.
CommandTarget - указывает на элемент который нужно распечатать.
CommandParameter - на свойство VM.

Добавлено через 5 минут
firnen_dragon, опять таки, имейте ввиду, что речь идёт о ПРАВИЛЬНОЙ реализации.
Но если хочется "срезать углы", то можно и из VM вызывать.
Тогда к печатному диалогу следует относится как к любому другому диалогу.
Здесь проблема только с передачей Visual.
Можно конечно его скрыть за object - типа это печать не только Visual, но и любого объекта.
Но, по мне, смотрится такое решение очень криво.

Добавлено через 24 минуты
Цитата Сообщение от firnen_dragon Посмотреть сообщение
ComboBoxItem SelectedMode
А зачем это свойство в VM?
1
 Аватар для firnen_dragon
25 / 25 / 4
Регистрация: 21.01.2019
Сообщений: 407
12.02.2024, 18:57  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
CommandTarget - указывает на элемент который нужно распечатать.
CommandParameter - на свойство VM.
А как их передавать теперь?
XML
1
<Button Content="Распечатать" Margin="10" Grid.Column="1" Command="{x:Static helpers:PrintHelper.Start}" CommandTarget ="{Binding ElementName=image}" CommandParameter="{Binding SelectedMode}"/>
C#
1
public static readonly ICommand Start = new RelayCommand<Visual, ComboBoxItem>(Print);
Цитата Сообщение от Элд Хасп Посмотреть сообщение
firnen_dragon, опять таки, имейте ввиду, что речь идёт о ПРАВИЛЬНОЙ реализации.
Но если хочется "срезать углы", то можно и из VM вызывать.
Стараюсь делать правильно по МВВМ на сколько это возможно, дабы расширять пул знаний в этой области, проблема только одна: из-за того что это реальные проекты, времени часто не хватает чтоб на "правильность" заморачиваться

Добавлено через 3 минуты
Цитата Сообщение от Элд Хасп Посмотреть сообщение
А зачем это свойство в VM?
Я передаю это свойство в одной из команд в VM
C#
1
public async virtual void OnGenerateQr(object Value = null) => await  _modelService.Model.GenerateQr(SelectedMode.Content.ToString(), Count, Scale,ProductDesignation, FactoryNumber,SoftwareVersion, Description);
А где оно должно быть?
0
 Аватар для xellan24rus
364 / 296 / 55
Регистрация: 08.04.2020
Сообщений: 1,175
12.02.2024, 20:19
Цитата Сообщение от firnen_dragon Посмотреть сообщение
проблема только одна: из-за того что это реальные проекты, времени часто не хватает чтоб на "правильность" заморачиваться
Проблема только заключается в осознанности действий порой. Вспомните с чего начинали, когда писали код целиком в одном методе, в одном классе. Выходила каша которую сложно понимать. Но развиваясь узнали про декомпозицию, архитектуру. Стали ею пользоваться, стало легче читать код, легче искать в нем проблемы. Эти мелкие реализации тоже отнимают больше времени чем писанина в одном месте. Но с наработкой опыта декомпозиция\архитектура становится частью ваших всех решений. И тут также кажется что это долго всё, но на самом не так долго, дольше уходит времени на понимание и на практику начального, нового опыта.
Возможно я в чем то не прав, но я это понимаю так для себя.

Цитата Сообщение от firnen_dragon Посмотреть сообщение
А как их передавать теперь?
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public static class PrintCommand
{
    public static RoutedCommand Print = new RoutedCommand();
 
    static PrintCommand()
    {
        CommandManager.RegisterClassCommandBinding(typeof(UIElement), new CommandBinding(Print, ExecutePrintCommand));
    }
 
    private static void ExecutePrintCommand(object sender, ExecutedRoutedEventArgs e)
    {
        UIElement target = e.Source as UIElement;
        if (target != null)
        {
            PrintDialog printDialog = new PrintDialog();
            if (printDialog.ShowDialog() == true)
            {
                printDialog.PrintVisual(target, "Печать элемента");
            }
        }
    }
}
XML
1
<Button Content="Print" Command="{x:Static Printing:PrintCommand.Print}" CommandTarget="{Binding ElementName=image}" />
Добавлено через 5 минут
Цитата Сообщение от firnen_dragon Посмотреть сообщение
Я передаю это свойство в одной из команд в VM
Кроме сервисов можно использовать конверторы и разные биндинги команд и т.п, это относится к view, то есть вы ничего не нарушаете
1
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16165 / 11285 / 2891
Регистрация: 21.04.2018
Сообщений: 33,174
Записей в блоге: 2
12.02.2024, 22:34
Цитата Сообщение от firnen_dragon Посмотреть сообщение
А как их передавать теперь?
RoutedCommand отрабатываются через CommandBinding.
Сегодня занят. Покажу как будет время.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
12.02.2024, 22:34

Вывод на 3D-печать векторного изображения брелка.
всем привет! у меня есть векторное изображение и 3д притер,но нет опыта работы в сфере моделирования, мне нужно из этого сделать брелок,как...

[MVVM] Вставка изображения в RichTextBox
Здравствуйте уважаемые программисты. Я решив изучить WPF + MVVM, столкнулся с некоторыми трудностями. У меня есть RichTextBox и не...

Вывод на печать DBGrid из TabSheet на печать в файл ворда
Здравствуйте, не могли бы помочь с выводом на печать? В делфи 10 подключена база и информация выводится в DBGrid на TabSheet. Необходимо...

Печать изображения
Нужно сделать программу для печати музыкальных перфокарт для музкальной шкатулки фиксированного размера, но не представляю как перевести...

Печать изображения
При отправки изображения на печать сразу происходит печать, но нужно что бы сначала появлялось такое вот окно: как этого добиться? ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
60
Ответ Создать тему
Новые блоги и статьи
Был там один разговор по поводу свободы в материальном мире.
kumehtar 19.08.2026
Суть: рассматривается живое существо, оказавшееся внутри довольно странной системы (этого мира) и пытающееся обустроить в ней свой кусок пространства. Жизнь действительно предъявляет каждому. . .
Когда логика программы не спасает от человеческих ошибок
Maks 18.08.2026
В последнее время всё чаще и чаще сталкиваюсь с таким явлением, как абсолютная невнимательность (или глупость) пользователей. Проявляется это чаще всего на работе в коллективе. Допустим, человек с. . .
Лето уходит
kumehtar 17.08.2026
Мысли в слух
kumehtar 17.08.2026
Забавно, насколько сейчас стала доступна информация. Например о магии, духовном развитии, медитациях, и других подобных направлениях, ранее зачастую тайных, передаваемых от учителя к ученику. Хотя. . .
Перемещение строк из ТЧ в другой документ с учетом текущего пробега
Maks 17.08.2026
Реализация из решения ниже выполнена на примере нетипового документа "Автозапчасти", с ТЧ "Шины". За основу взят алгоритм отсюда: https:/ / www. cyberforum. ru/ blogs/ 359708/ 10838. html Задача: . . .
Саморегулирующийся социальный контракт для сервера cross-section.
Hrethgir 14.08.2026
С кодом конечно таких глубоких размышлений пока не было, впрочем я уже привык к алгоритмизации. Суть предмета записи: снова в диалоге с нейросетью (я взял пока себе ник для учётки админа - Rector). . . .
Часы электронные
Uhbif79 12.08.2026
Выкладываю программу часов. Программа позволяет: 1. Использовать системное время и дату, 2. Есть возможность вводить время и дату вручную. 3. Реализованы 2 будильника: начало и конец рабочего дня. . . .
Часы с будильником на основе класса QLCDNumber
Uhbif79 12.08.2026
Всем добрый день, выкладываю программу часов с будильником на основе класса QLCDNumber. Здесь я пробовал самостоятельно создавал классы, впервые столкнулся с видимостью переменной одного класса из. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru