Skip to content

WPF UI Violeta is based on WPF UI, and provides the Fluent experience in your known and loved WPF framework.

License

Notifications You must be signed in to change notification settings

emako/wpfui.violeta

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

WPF UI Banner Dark

WPF UI Banner Light

WPF UI Violeta

GitHub license NuGet VS 2022 Downloads Actions Platform

WPF UI Violeta is based on WPF UI, and provides the Fluent experience in your known and loved WPF framework. Some new immersive controls like Toast, Flyout, ContentDialog, MessageBox and etc.

Some idea or codes are ported from ModernWpf and Fischless.

When I decided to create this project I was listening to the song Violeta.

๐Ÿš€ Getting started

Similar to WPF UI.

<Application
    xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml"
    xmlns:vio="http://schemas.lepo.co/wpfui/2022/xaml/violeta">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ui:ThemesDictionary Theme="Dark" />
                <ui:ControlsDictionary />
                <vio:ThemesDictionary Theme="Dark" />
                <vio:ControlsDictionary />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
</Application>

๐Ÿ‘‹Examples

Wpf.Ui.Test

  • Toast

    Toast is an independent popup notification that automatically disappears after a specified time.

    Toast.Information("I am information message");
    Toast.Error("I am error message");
    Toast.Success("I am success message");
    Toast.Warning("I am warning message");
    Toast.Show(owner: null!, "I am any message",  new ToastConfig());
  • Flyout

    The FlyoutService enables you to attach Flyout menus or tooltips to various controls such as Button, providing a flexible and intuitive way to display additional content or options.

    <ui:Button Content="Show Flyout">
        <ui:FlyoutService.Flyout>
            <ui:Flyout Placement="Bottom">
                <StackPanel>
                    <TextBlock
                        HorizontalAlignment="Left"
                        Text="Show the flyout message here" />
                     <Button
                       Command="{Binding GotItCommand}"
                       Content="Got it" />
                </StackPanel>
            </ui:Flyout>
        </ui:FlyoutService.Flyout>
    </ui:Button>
  • ContentDialogHostService

    The ContentDialogHostService simplifies the creation and management of ContentDialog instances in your application.

    Wpf.Ui.Controls.ContentDialog dialog = new()
    {
        Title = "My sample dialog",
        Content = "Content of the dialog",
        CloseButtonText = "Close button",
        PrimaryButtonText = "Primary button",
        SecondaryButtonText = "Secondary button"
    };
    
    // Setting the dialog container
    dialog.DialogHost = ContentDialogHostService.ContentPresenterForDialogs;
    
    // Showing the dialog
    await dialog.ShowAsync(CancellationToken.None);
  • ContentDialog

    The new ContentDialog is easy to use with smooth transitions.

    global using ContentDialog = Wpf.Ui.Violeta.Controls.ContentDialog;
    global using ContentDialogButton = Wpf.Ui.Violeta.Controls.ContentDialogButton;
    
    ContentDialog dialog = new()
    {
        Title = "My sample dialog",
        Content = "Content of the dialog",
        CloseButtonText = "Close button",
        PrimaryButtonText = "Primary button",
        SecondaryButtonText = "Secondary button",
        DefaultButton = ContentDialogButton.Primary,
    };
    
    _ = await dialog.ShowAsync();

โ€‹ If you want to inherit Wpf.Ui.Violeta.Controls.ContentDialog to implement a custom dialog just using Style="{StaticResource DefaultVioletaContentDialogStyle}".

  • MessageBox

    To utilize Win32's classic MessageBox methods while supporting modern UI themes like Mica and dark mode.

    global using MessageBox = Wpf.Ui.Violeta.Controls.MessageBox;
    
    // Sync methods
    _ = MessageBox.Information("This is a information message");
    _ = MessageBox.Warning("This is a warning message");
    _ = MessageBox.Error("This is a error message");
    MessageBoxResult result =  MessageBox.Question("This is a question and do you want to click OK?");
    
    // Async methods
    _ = await MessageBox.InformationAsync("This is a information message");
    _ = await MessageBox.WarningAsync("This is a warning message");
    _ = await MessageBox.ErrorAsync("This is a error message");
    MessageBoxResult result = await MessageBox.QuestionAsync("This is a question and do you want to click OK?");
  • PendingBox

    Keep displaying 'Loading' until released.

    // Default style.
    using IPendingHandler pending = PendingBox.Show();
    
    // Show with title and cancel button.
    using IPendingHandler pending = PendingBox.Show("Doing something", "I'm a title", isShowCancel: true);
  • ToggleButtonGroup / RadioButtonGroup / MenuItemGroup

    Turn the ToggleButton and RadioButton under the same Group into a radio button.

    <StackPanel Orientation="Horizontal">
        <StackPanel.Resources>
            <vio:ToggleButtonGroup x:Key="ToggleButtonGroup" />
        </StackPanel.Resources>
        <ToggleButton
            vio:ToggleButtonGroup.Group="{DynamicResource ToggleButtonGroup}"
            Content="1st"
            IsChecked="True" />
        <ToggleButton
            vio:ToggleButtonGroup.Group="{DynamicResource ToggleButtonGroup}"
            Content="2nd" />
    </StackPanel>
    <StackPanel Orientation="Horizontal">
        <StackPanel.Resources>
            <vio:RadioButtonGroup x:Key="RadioButtonGroup" />
        </StackPanel.Resources>
        <RadioButton
                     vio:RadioButtonGroup.Group="{DynamicResource RadioButtonGroup}"
                     Content="1st"
                     IsChecked="True" />
        <Grid>
            <RadioButton
                         Margin="8,0,0,0"
                         vio:RadioButtonGroup.Group="{DynamicResource RadioButtonGroup}"
                         Content="2nd" />
        </Grid>
    </StackPanel>
  • Splash

    Show the Splash Screen in another UI thread.

    public App()
    {
        Splash.ShowAsync("pack://application:,,,/Wpf.Ui.Test;component/wpfui.png");
        InitializeComponent();
    }
    
    public MainWindow()
    {
        InitializeComponent();
        Splash.CloseOnLoaded(this, minimumMilliseconds: 1800);
    }
  • TreeListView

    TreeListView is a better way to display hierarchical data.

    <ui:TreeListView ItemsSource="{Binding StaffList}">
        <ui:TreeListView.Columns>
            <GridViewColumnCollection>
                <ui:GridViewColumn Width="400" Header="Name">
                    <ui:GridViewColumn.CellTemplate>
                        <DataTemplate>
                            <ui:TreeRowExpander Content="{Binding Name}" />
                        </DataTemplate>
                    </ui:GridViewColumn.CellTemplate>
                </ui:GridViewColumn>
                <ui:GridViewColumn
                                   Width="80"
                                   DisplayMemberBinding="{Binding Age}"
                                   Header="Age" />
                <ui:GridViewColumn
                                   Width="80"
                                   DisplayMemberBinding="{Binding Sex}"
                                   Header="Sex" />
                <ui:GridViewColumn
                                   Width="100"
                                   DisplayMemberBinding="{Binding Duty}"
                                   Header="Duty" />
                <ui:GridViewColumn Width="250" Header="IsChecked">
                    <ui:GridViewColumn.CellTemplate>
                        <DataTemplate>
                            <ui:ToggleSwitch IsChecked="{Binding IsChecked}" />
                        </DataTemplate>
                    </ui:GridViewColumn.CellTemplate>
                </ui:GridViewColumn>
            </GridViewColumnCollection>
        </ui:TreeListView.Columns>
        <ui:TreeListView.ItemTemplate>
            <HierarchicalDataTemplate ItemsSource="{Binding StaffList}" />
        </ui:TreeListView.ItemTemplate>
    </ui:TreeListView>
    public partial class ViewModel : ObservableObject
    {
        [ObservableProperty]
        private ObservableCollection<Staff> staffList = [];
        
        public void InitNode1Value()
        {
            Staff staff = new Staff()
            {
                Name = "Alice",
                Age = 30,
                Sex = "Male",
                Duty = "Manager",
                IsExpanded = true
            };
            Staff staff2 = new Staff()
            {
                Name = "Alice1",
                Age = 21,
                Sex = "Male",
                Duty = "Normal",
                IsExpanded = true
            };
            Staff staff3 = new Staff()
            {
                Name = "Alice11",
                Age = 21,
                Sex = "Male",
                Duty = "Normal"
            };
            staff2.StaffList.Add(staff3);
            staff3 = new Staff()
            {
                Name = "Alice22",
                Age = 21,
                Sex = "Female",
                Duty = "Normal"
            };
            staff2.StaffList.Add(staff3);
            staff.StaffList.Add(staff2);
            staff2 = new Staff()
            {
                Name = "Alice2",
                Age = 22,
                Sex = "Female",
                Duty = "Normal"
            };
            staff.StaffList.Add(staff2);
            staff2 = new Staff()
            {
                Name = "Alice3",
                Age = 23,
                Sex = "Female",
                Duty = "Normal"
            };
            staff.StaffList.Add(staff2);
            StaffList.Add(staff);
    
            staff = new Staff()
            {
                Name = "Bob",
                Age = 31,
                Sex = "Male",
                Duty = "CEO"
            };
            staff2 = new Staff()
            {
                Name = "Bob1",
                Age = 24,
                Sex = "Female",
                Duty = "Normal"
            };
            staff.StaffList.Add(staff2);
            staff2 = new Staff()
            {
                Name = "Bob2",
                Age = 25,
                Sex = "Female",
                Duty = "Normal"
            };
            staff.StaffList.Add(staff2);
            staff2 = new Staff()
            {
                Name = "Bob3",
                Age = 26,
                Sex = "Male",
                Duty = "Normal"
            };
            staff.StaffList.Add(staff2);
            StaffList.Add(staff);
    
            staff = new Staff()
            {
                Name = "Cyber",
                Age = 32,
                Sex = "Female",
                Duty = "Leader"
            };
            staff2 = new Staff()
            {
                Name = "Cyber1",
                Age = 27,
                Sex = "Female",
                Duty = "Normal"
            };
            staff.StaffList.Add(staff2);
            staff2 = new Staff()
            {
                Name = "Cyber2",
                Age = 28,
                Sex = "Female",
                Duty = "Normal"
            };
            staff.StaffList.Add(staff2);
            StaffList.Add(staff);
        }
    }
    
    public partial class Staff : ObservableObject
    {
        [ObservableProperty]
        private string name = null!;
    
        [ObservableProperty]
        private int age;
    
        [ObservableProperty]
        private string sex = null!;
    
        [ObservableProperty]
        private string duty = null!;
    
        [ObservableProperty]
        private bool isChecked = true;
    
        [ObservableProperty]
        private bool isSelected = false;
    
        [ObservableProperty]
        private bool isExpanded = false;
    
        [ObservableProperty]
        private ObservableCollection<Staff> staffList = [];
    }
  • TreeModelListView

    TreeModelListView is a fast tree list view used IEnumerable and ITreeModel to display data but CURD is not fully supported.

    <ui:TreeModelListView Model="{Binding TreeTestModel}">
     <ui:GridView>
         <ui:GridView.Columns>
             <ui:GridViewColumn Width="400" Header="Column1">
                 <ui:GridViewColumn.CellTemplate>
                     <DataTemplate>
                         <ui:TreeModelRowExpander Content="{Binding Column1}" />
                     </DataTemplate>
                 </ui:GridViewColumn.CellTemplate>
             </ui:GridViewColumn>
             <ui:GridViewColumn
                 Width="250"
                 DisplayMemberBinding="{Binding Column2, Mode=TwoWay}"
                 Header="Column2" />
             <ui:GridViewColumn
                 Width="250"
                 DisplayMemberBinding="{Binding Column3, Mode=TwoWay}"
                 Header="Column3" />
             <ui:GridViewColumn Width="250" Header="IsChecked">
                 <ui:GridViewColumn.CellTemplate>
                     <DataTemplate>
                         <ui:ToggleSwitch IsChecked="{Binding IsChecked}" />
                     </DataTemplate>
                 </ui:GridViewColumn.CellTemplate>
             </ui:GridViewColumn>
         </ui:GridView.Columns>
     </ui:GridView>
    </ui:TreeModelListView>
    public partial class ViewModel : ObservableObject
    {
        [ObservableProperty]
        private TreeCollection<TreeTestModel> treeTestModel = CreateTestModel();
        
        public static TreeModelCollection<TreeTestModel> CreateTestModel()
        {
            return new TreeModelCollection<TreeTestModel>()
            {
                Children = new(
                [
                    new()
                    {
                        Column1 = "Test 1",
                        Column2 = "Test 1",
                        Column3 = "Test 1",
                        Children = new(
                        [
                            new()
                            {
                                Column1 = "Test 1.1",
                                Column2 = "Test 1.1",
                                Column3 = "Test 1.1",
                                Children = new(
                                [
                                    new()
                                    {
                                        Column1 = "Test 1.2",
                                        Column2 = "Test 1.2",
                                        Column3 = "Test 1.2",
                                    },
                                ]),
                            },
                        ]),
                    },
                    new()
                    {
                        Column1 = "Test 2",
                        Column2 = "Test 2",
                        Column3 = "Test 2",
                    }
                ]),
            };
        }
    }
    
    [ObservableObject]
    public partial class TreeTestModel : TreeModelObject<TreeTestModel>
    {
        [ObservableProperty]
        private string? column1;
    
        [ObservableProperty]
        private string? column2;
    
        [ObservableProperty]
        private string? column3;
    
        [ObservableProperty]
        private bool isChecked = false;
    }
  • ImageView

    Provides a scalable image control.

    <vio:ImageView Source="/wpfui.png" />
  • ExceptionReport

    Show a dialog to handle the DispatcherUnhandledException from Application.

    public partial class App : Application
    {
       public App()
       {
           InitializeComponent();
    
           DispatcherUnhandledException += (object s, DispatcherUnhandledExceptionEventArgs e) =>
           {
               e.Handled = true;
               ExceptionReport.Show(e.Exception);
           };
       }
    }
  • BitmapIcon

    Supports to show monochrome image that match the theme color.

    <ui:BitmapIcon
                  ShowAsMonochrome="False"
                  UriSource="pack://application:,,,/Wpf.Ui.Test;component/Resources/Images/Tiara.png" />
    <ui:BitmapIcon
                  ShowAsMonochrome="True"
                  UriSource="pack://application:,,,/Wpf.Ui.Test;component/Resources/Images/Tiara.png" />

๐Ÿ“ท Screenshots

Under construction

Thanks