3
<UserControl x:Class="MyApp.PrinterSelection"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:Printing="clr-namespace:System.Drawing.Printing;assembly=System.Drawing"
             xmlns:local="clr-namespace:MyApp"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">

<Grid>

        <ListBox x:Name="displayInstalledPrinterListView" HorizontalAlignment="Left" Height="311" Margin="10,0,0,0" VerticalAlignment="Top" Width="499" ItemsSource="{x:Static Printing:PrinterSettings.InstalledPrinters}" SelectionChanged="displayInstalledPrinterListView_SelectionChanged" AlternationCount="2" FontSize="16"/>
    </Grid>

how can I indicate which printer in the ListBox is the default printer using XAML. If it's not possible to do this with XAML, then whats the best approach?

I know I can programatically check each printer to see if IsDefaultPrinter is true. However I wanted to know if this can be done with XAML (only)

software is fun
  • 7,286
  • 18
  • 71
  • 129
  • Check this link out here --> http://stackoverflow.com/questions/86138/whats-the-best-way-to-get-the-default-printer-in-net good info there – waltmagic May 13 '15 at 21:42
  • is there a way to IsDefaultPrinte using XAML? – software is fun May 13 '15 at 21:52
  • 1
    "using XAML" There is still C# in your programming project right? Alexander's answer should work well for any case. Apply Alexander's answer in your C# code and you should find success. – waltmagic May 13 '15 at 22:03
  • @waltmagic System.Printing.LocalPrintServer doesn't exist. Can you show some sample code? – software is fun May 13 '15 at 22:37
  • Did you add the reference for System.Printing.LocalPrintServer to your project? If not it will tell you it doesn't exist. If you want an example check out the official Microsoft Documentation here --> System.Printing.LocalPrintServer – waltmagic May 13 '15 at 22:42
  • No Items found when trying to find the reference assembly – software is fun May 13 '15 at 22:43
  • I have to go afk for the day but if you read through the API for System.Printing.LocalPrintServer and add the reference, instructions here --> https://msdn.microsoft.com/en-us/library/wkze6zky.aspx you will get what you want. I just can't provide the code for you today. Hope this helps you get where you need to go! – waltmagic May 13 '15 at 22:47
  • A reference to `System.Drawing` is also required to use the `PrinterSettings` class. – Koopakiller May 13 '15 at 22:57
  • 1
    In what way do you want to "indicate which printer...is the default printer"? The code you show just displays the printer names. Do you want the default printer to be displayed in a different text color? Background? Just add some text to the name that's shown? Something else? It is not hard to do what you want, but the exact technique depends on the specific change in the visual presentation you are trying to achieve. – Peter Duniho May 14 '15 at 02:49

2 Answers2

1

It's not entirely clear to me what specifically you are having trouble with, nor how you want the visual display of the printer names to change. So, here is a general-purpose example of a XAML-only implementation that displays all of the installed printers, along with the name of the current default printer:

<Window x:Class="TestSO30225596DefaultPrinter.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:Printing="clr-namespace:System.Printing;assembly=System.Printing"
        Title="MainWindow" Height="350" Width="525">
  <Window.Resources>
    <Printing:LocalPrintServer x:Key="localPrintServer1"/>
    <ObjectDataProvider x:Key="printerCollection"
                        ObjectInstance="{StaticResource localPrintServer1}"
                        MethodName="GetPrintQueues">
      <ObjectDataProvider.MethodParameters>
        <x:ArrayExtension Type="{x:Type Printing:EnumeratedPrintQueueTypes}">
          <Printing:EnumeratedPrintQueueTypes>Local</Printing:EnumeratedPrintQueueTypes>
          <Printing:EnumeratedPrintQueueTypes>Connections</Printing:EnumeratedPrintQueueTypes>
        </x:ArrayExtension>
      </ObjectDataProvider.MethodParameters>
    </ObjectDataProvider>
  </Window.Resources>
  <Grid>
    <Grid.RowDefinitions>
      <RowDefinition Height="*"/>
      <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>
    <ListBox x:Name="displayInstalledPrinterListView"
             HorizontalAlignment="Left" VerticalAlignment="Top"
             Height="311" Width="499" Margin="10,0,0,0"
             ItemsSource="{Binding Source={StaticResource printerCollection}}"
             AlternationCount="2" FontSize="16">
      <ListBox.ItemTemplate>
        <DataTemplate>
          <StackPanel Orientation="Horizontal">
            <TextBlock Text="{Binding Name}"/>
          </StackPanel>
        </DataTemplate>
      </ListBox.ItemTemplate>
    </ListBox>
    <StackPanel Orientation="Horizontal" Grid.Row="1">
      <TextBlock Text="Default Printer: "/>
      <TextBlock Text="{Binding Source={StaticResource localPrintServer1}, Path=DefaultPrintQueue.Name}"/>
    </StackPanel>
  </Grid>
</Window>

Note that you will need to add a reference to the WPF-compatible System.Printing.dll assembly. The above technically meets your broad specification, i.e. it does indicate (through the text displayed below the ListBox) which printer is the default.

I trust that given the above example, you can modify it to suit your specific needs, by using the DefaultPrintQueue.Name property value to compare with the actual name of each printer, and present whatever indication you deem most appropriate based on that.

Peter Duniho
  • 68,759
  • 7
  • 102
  • 136
1

You can use following code:

XAML:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApplication1"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <ComboBox HorizontalAlignment="Center" VerticalAlignment="Center" ItemsSource="{Binding Printers}">
            <ComboBox.ItemTemplate>
                <DataTemplate DataType="{x:Type local:PrinterWrapper}">
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="Auto"/>
                            <ColumnDefinition Width="*"/>
                        </Grid.ColumnDefinitions>
                        <TextBlock Text="Default - " x:Name="default" Visibility="Collapsed"/>
                        <TextBlock Text="{Binding PrinterName}" Grid.Column="1" />
                    </Grid>
                    <DataTemplate.Triggers>
                        <DataTrigger Binding="{Binding IsDefaultPrinter}" Value="True">
                            <Setter TargetName="default" Property="Visibility" Value="Visible"/>
                        </DataTrigger>
                    </DataTemplate.Triggers>
                </DataTemplate>
            </ComboBox.ItemTemplate>
        </ComboBox>
    </Grid>
</Window>

Code Behind:

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Printing;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfApplication1
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = new ViewModel();
        }
    }

    public class ViewModel
    {
        public ObservableCollection<PrinterWrapper> Printers { get; set; }

        public ViewModel()
        {
            this.Printers = new ObservableCollection<PrinterWrapper>();

            LocalPrintServer server = new LocalPrintServer();
            var printQueues = server.GetPrintQueues(new EnumeratedPrintQueueTypes[] { EnumeratedPrintQueueTypes.Local, EnumeratedPrintQueueTypes.Connections });
            foreach (var printQueue in printQueues)
            {
                var printerWrapper = new PrinterWrapper();
                printerWrapper.PrinterName = printQueue.Name;
                printerWrapper.IsDefaultPrinter = (printQueue.Name == server.DefaultPrintQueue.Name);

                this.Printers.Add(printerWrapper);
            }
            server.Dispose(); // Depends on you :-)
        }
    }
    public class PrinterWrapper
    {
        public string PrinterName { get; set; }
        public bool IsDefaultPrinter { get; set; }
    }
}

Note: PrinterWrapper class you can use to accommodate more printer related properties and in ViewModel you can write your printing logic. Also instead of showing just the text Default before the default printer name, you can use some image or some other fancy stuff.

Prince Owen
  • 1,225
  • 12
  • 20
Nitin Joshi
  • 1,638
  • 1
  • 14
  • 17