.

Starting a WPF app programmatically (without a startup uri)

The default project template for WPF applications assumes that you want your main application class to be xaml-based. However, this is not a requirement and you can change it. Doing so allows you to write your own application entry point method and create your own application instance configured the way that you want.

So, you can delete your App.xaml and App.xaml.cs files and create an App.cs file in their place. In that file, do something like this:

internal class App : Application
{
    [STAThread]
    public static int Main(string[] args)
    {
        App app = new App();
        // Setup your application as you want before running it
        return app.Run(new MainWindow());
    }

    public App()
    {
        // (Optional) Load your application resources file (which has a "Page" build action, not "ApplicationDefinition",
        // and a root node of type "ResourceDictionary", not "Application")
        Resources = (ResourceDictionary)Application.LoadComponent(new Uri("/MyAssemblyName;component/Resources.xaml", UriKind.Relative));
    }
}

This allows you specify your main window whichever way you want before running the application. Your application resources file would look something like this:

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <!-- Put application resources here -->
</ResourceDictionary>

I always structure my WPF applications this way because it seems simpler and provides more control over how the application is run. (I created a custom WPF application project template in Visual Studio.)

Simple WPF input prompt

This is the simplest way to prompt a user for input from a WPF app:

var inputBox = Microsoft.VisualBasic.Interaction.InputBox("Prompt here",
                            "Title here",
                            "Default data",
                            -1, -1);
if (inputBox == "")
    return;

you have to add a reference to the Microsoft.VisualBasic assembly

 

WPF stringformat currency to pound (£)

default formatting of currencies etc happens to US, so to override that for GB / UK etc. :

<TextBlock Text="{Binding Path=CurrentPrice, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, StringFormat={}{0:c}, ConverterCulture=en-GB}" />

WPF confirmation boxes

MessageBoxResult answer = MessageBox.Show("Do you want to delete this contact?", "Confirmation", MessageBoxButton.YesNo, MessageBoxImage.Question);
if (answer == MessageBoxResult.Yes)
{
    Person.DeletedDate = DateTime.Now;
    new TheDataService().UpdatePerson(Person);
}

Working with commands in WPF

safd

#region CloseCommand

private RelayCommand _closeCommand;

public ICommand CloseCommand
{
    get
    {
        if (_closeCommand == null)
        {
            _closeCommand = new RelayCommand(p => OnClose(), p => CanClose());
        }

        return _closeCommand;
    }
}

private bool CanClose()
{
    return true;
}

private void OnClose()
{
    Workspace.This.Close(this);
}

#endregion

Implementation for RelayCommand:

internal class RelayCommand : ICommand
{
    #region Fields

    private readonly Action<object> _execute;
    private readonly Predicate<object> _canExecute;

    #endregion // Fields

    #region Constructors

    public RelayCommand(Action<object> execute)
        : this(execute, null)
    {
    }

    public RelayCommand(Action<object> execute, Predicate<object> canExecute)
    {
        if (execute == null)
            throw new ArgumentNullException("execute");

        _execute = execute;
        _canExecute = canExecute;
    }

    #endregion // Constructors

    #region ICommand Members

    public bool CanExecute(object parameter)
    {
        return _canExecute == null ? true : _canExecute(parameter);
    }

    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }

    public void Execute(object parameter)
    {
        _execute(parameter);
    }

    #endregion // ICommand Members
}

df

 

Gridview in WPF

<ListView ItemsSource="{Binding Path=., Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" MaxHeight="430">
    <ListView.View>
        <GridView>
            <GridViewColumn Header="Date" DisplayMemberBinding="{Binding SentTimestamp, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
            <GridViewColumn Header="Subject" DisplayMemberBinding="{Binding Subject, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
            <GridViewColumn Header="Attachment"  DisplayMemberBinding="{Binding HasAttachments, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
        </GridView>
    </ListView.View>
    <ListView.ItemContainerStyle>
        <Style TargetType="{x:Type ListBoxItem}">
            <!--<EventSetter Event="PreviewMouseLeftButtonDown" Handler="ListBox_MouseLeftButtonDown" />-->
        </Style>
    </ListView.ItemContainerStyle>
</ListView>

Terminating a WPF application

You could shutdown the app programatically as follow:

Application.Current.Shutdown();

or you could simply force a more disgraceful close:

Process.GetCurrentProcess().Kill(); 
Environment.Exit(0);

Working with ListViews in WPF

This will bind a datasource to a ListView and display it. It includes a event for mouse left button down

<ListView ItemsSource="{Binding Path=., Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" MaxHeight="430">
    <ListView.ItemTemplate>
        <DataTemplate>
            <DockPanel LastChildFill="True">
                <TextBlock Text="{Binding FullName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
            </DockPanel>
        </DataTemplate>
    </ListView.ItemTemplate>
    <ListView.ItemContainerStyle>
        <Style TargetType="{x:Type ListBoxItem}">
            <EventSetter Event="PreviewMouseLeftButtonDown" Handler="ListBox_MouseLeftButtonDown" />
        </Style>
    </ListView.ItemContainerStyle>
</ListView>

Enjoy!

Allowing drag and drop in WPF

This will allow you to do drag and drop in WPF:

public THIS_IS_THE_WPF_FORM_CONSTRUCTOR()
{
    InitializeComponent();

    AllowDrop = true;

    DragEnter += Form_DragEnter;
    Drop += Form_DragDrop;
}

private void Form_DragEnter(object sender, DragEventArgs e)
{
    if (e.Data.GetDataPresent(DataFormats.Html))
        e.Effects = DragDropEffects.Copy;
    else
        e.Effects = DragDropEffects.None;
    e.Handled = true;
}

private void Form_DragDrop(object sender, DragEventArgs e)
{
    if (!e.Data.GetDataPresent(DataFormats.Html))
        return;

    var data = e.Data.GetData(DataFormats.Text, false);
    var url = (string)data;

    MessageBox.Show(url);
}

you can also try this example:

 

<Window x:Class="FileManager.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <DockPanel LastChildFill="True">
        <Button Content="Dock=Top" DockPanel.Dock="Top"/>
        <Button Content="Dock=Bottom" DockPanel.Dock="Bottom"/>
        <StackPanel Orientation="Horizontal"  DockPanel.Dock="Left">
            <ListView Width="auto">
                <ListView.View>
                    <GridView>
                        <GridView.ColumnHeaderContainerStyle>
                            <Style>
                                <Setter Property="FrameworkElement.Visibility" Value="Collapsed"/>
                            </Style>
                        </GridView.ColumnHeaderContainerStyle>
                        <GridView.Columns>

                        </GridView.Columns>
                    </GridView>
                </ListView.View>
            </ListView>
            <TreeView HorizontalAlignment="Left" Height="auto"  VerticalAlignment="Top" Width="100">

            </TreeView>
        </StackPanel>
        <ListBox Width="200px" DockPanel.Dock="Right" Name="dropbox" DragEnter="Dropbox_OnDragEnter" Drop="Dropbox_OnDrop" AllowDrop="True">

        </ListBox>
        <Button Content="LastChildFill=True"/>
    </DockPanel>
</Window>

with this code:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
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 FileManager
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Dropbox_OnDragEnter(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop, false))
                e.Effects = DragDropEffects.All;
            else
                e.Effects = DragDropEffects.None;
        }

        private void Dropbox_OnDrop(object sender, DragEventArgs e)
        {
            List<string> filepaths = new List<string>();
            List<string> folderpaths = new List<string>();
            foreach (var s in (string[])e.Data.GetData(DataFormats.FileDrop, false))
            {
                if (Directory.Exists(s))
                {
                    //Add files from folder
                    folderpaths.Add(s);
                    //folderpaths.AddRange(Directory.GetFiles(s));
                }
                else if (File.Exists(s))
                {
                    //Add filepath
                    filepaths.Add(s);
                }
            }
        }
    }
}

Spacing (styling) child elements in WPF

You can style your WPF child elements as follow:

<StackPanel Orientation="Horizontal" HorizontalAlignment="Left" DockPanel.Dock="Top"  >
    <StackPanel.Resources>
        <Style TargetType="{x:Type Button}">
            <Setter Property="Margin" Value="10,10,0,10"/>
        </Style>
    </StackPanel.Resources>

    <Button Content="Button" Width="75"/>
    <Button Content="Button" Width="75"/>
</StackPanel>

Another quick way to do something similar:

<StackPanel local:MarginSetter.Margin="5">
   <TextBox Text="hello" />
   <Button Content="hello" />
   <Button Content="hello" />
</StackPanel>

In case you would want to re-use the margin between two containers, you can convert the margin value to a resource in an outer scope, f.e.

<Window.Resources>
    <Thickness x:Key="tbMargin">0,10,0,0</Thickness>
</Window.Resources>

and then refer to this value in the inner scope

<StackPanel.Resources>
    <Style TargetType="{x:Type TextBox}">
        <Setter Property="Margin" Value="{StaticResource tbMargin}"/>
    </Style>
</StackPanel.Resources>