Multithread Proress bar in WPF

În this example, I have added the progress bar to the status bar and a start button in the WPF XAML code.
To add a progress bar to the status bar, Add the below codein XAML window:

<Window x:Class="WpfApplicationSample.Dispatcher.Progressbar"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApplicationSample.Dispatcher"
        mc:Ignorable="d"
      Title="ProgressBar" Height="105" Width="445" Background="Wheat" ResizeMode="NoResize">
    <Grid>
        <Button Content="Start" Height="23" Click="buttonStart_Click"  HorizontalAlignment="Right" Margin="0,15,15,0" Name="buttonStart" VerticalAlignment="Top" Width="75" />
        <StatusBar Name="StatusBar1" VerticalAlignment="Bottom" Background="Blue" Margin="0,0,0,0" />
    </Grid>
</Window>

I add the following code to the buttonStart_Click method in the code-behind.

        private void buttonStart_Click(object sender, RoutedEventArgs e)
        {
            buttonStart.IsEnabled = false;
            var SecondsToComplete = 30; //Program specific value

            var progress = new ProgressBar
            {
                IsIndeterminate = false,
                Orientation = Orientation.Horizontal,
                Width = 419,
                Height = 20
            };

            var duration = new Duration(TimeSpan.FromSeconds((SecondsToComplete * 1.35)));
            var doubleAnimatiion = new DoubleAnimation(200, duration);
            StatusBar1.Items.Add(progress);

            try
            {
                var uiThread = TaskScheduler.FromCurrentSynchronizationContext();

                Action MainThreadDoWork = new Action(() =>
                {
                    //add thread safe code here.
                    //Confirm thread will not use GUI thread
                    System.Threading.Thread.Sleep(20000);
                });

                Action ExecuteProgressBar = new Action(() =>
                {
                    progress.BeginAnimation(RangeBase.ValueProperty, doubleAnimatiion);
                });

                Action FinalThreadDoWOrk = new Action(() =>
                {
                    buttonStart.IsEnabled = true;
                    StatusBar1.Items.Remove(progress);
                });

                var mainThreadDoWorkTask = Task.Factory.StartNew(() => MainThreadDoWork());

                var executeProgressBarTask = new Task(ExecuteProgressBar);
                executeProgressBarTask.RunSynchronously();

                mainThreadDoWorkTask.ContinueWith(t => FinalThreadDoWOrk(), uiThread);
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error", ex.Message, MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }
Advertisements

WPF MultiTrigger

Triggers are used to change the style of a control when control’s property value changes or event fires. Triggers create visual effects on controls. By using triggers you can also change the appearance of framework elements. WPF exposes a property Style for every Control. For example, you would use a Trigger on IsMouseOver to respond to the mouse being over the control, and the setters might update a brush to show a style change.
A DataTrigger triggers on a data binding rather than on a control property. It is typically used in a DataTemplate. For example in my project we have a scenario where we need to change the colour of a data grid row for negative values, here you could use a DataTrigger to change the colour of an element in the data row.

<Style TargetType="{x:Type igGrid:DataRecordCellArea}">
  <Setter Property="ContextMenu" Value="{StaticResource ContextMenu}"/>
   <Style.Triggers>
   <DataTrigger Binding="{Binding Record.DataItem, RelativeSource={RelativeSource Self}, Converter={StaticResource RecordToHasHighlightConverter}}" Value="True">
    <Setter Property="Background" Value="#FFE5EFCE"/>
     <Setter Property="BackgroundAlternate" Value="#FFD7E4BC"/>
     </DataTrigger>
    </Style.Triggers>
</Style>

MultiTrigger and MultiDataTrigger are the same, except they allow you to specify multiple conditions (properties or bindings respectively) and take effect only when all conditions are satisfied.

<Window x:Class="WpfApplication3.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">
<Window.Resources>
        <Style x:Key="SampleMultTrigg" TargetType="{x:Type TextBox}" >
            <Style.Triggers>
                <MultiTrigger>
                    <MultiTrigger.Conditions>
                        <Condition Property="IsFocused" Value="True"></Condition>
                        <Condition Property="IsMouseOver" Value="True"></Condition>
                    </MultiTrigger.Conditions>
                    <MultiTrigger.Setters>
                        <Setter Property="Background" Value="yellow" ></Setter>
                    </MultiTrigger.Setters>
                </MultiTrigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>

    <StackPanel>
        <TextBox Style="{StaticResource SampleMultTrigg}"></TextBox>
    </StackPanel>
</Window>

Finally, EventTrigger is used to trigger actions in response to events (as opposed to changing one piece of state in response to another piece of state). For example, you could use an EventTrigger to respond to the MouseEnter event. EventTriggers are typically used to execute storyboards, for example to perform an animation when the event occurs.

Async Await in WPF

Asynchronous Programming is based on Task Parallel Library (TPL). As you probably know traditional techniques for writing asynchronous programs are very complicated in many aspects, so Async Programming comes to make our life easier when we write Multithreading applications.
Today we’ll see a very simple example of Async Programming using Async, Await and Task keywords in WPF application. Let’s build a simple WPF application with a button and a textbox. By pressing the button we call for some slow method (I named it SlowDude :). I don’t want GUI will be locked until the method will finish his job. In other words I want to call that method asynchronously.
XAML page:

<Window x:Class="WpfAsync.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="CodeArsenal.net" Height="180" Width="360">

    <DockPanel>
        <Button Name="buttonAsync" Height="50" Content="Async Example" 
                DockPanel.Dock="Top" Click="buttonAsync_Click"/>
        
        <TextBox Name="textBoxResults" DockPanel.Dock="Bottom" Margin="0,20,0,0"
                 TextWrapping="Wrap"
                 FontFamily="Lucida Console" 
                 FontSize="10"
                 AcceptsReturn="True"/>
    </DockPanel>
</Window>
        private async void buttonAsync_Click(object sender, RoutedEventArgs e)
        {
            ButtonAsync.IsEnabled = false;
            var slowTask = Task<string>.Factory.StartNew(() => SlowDude());
            TextBoxResults.Text += "Doing other things while waiting for that slow dude...\r\n";
            await slowTask;
            TextBoxResults.Text += slowTask.Result.ToString();
            ButtonAsync.IsEnabled = true;
        }
        private string SlowDude()
        {
            Thread.Sleep(2000);
            return "Ta-dam! Here I am!\r\n";
        }

Did you notice the async modifier in buttonAsync_Click method signature? This is crucial, because async modifier tells to compiler that this method contains code that will run asynchronously using await keyword.

Following code line actually calls for SlowDude method in asynchronous manner:

var slowTask = Task<string>.Factory.StartNew(() => SlowDude());  
await slowTask;

This command means – do other stuff that are between these two lines of code, without locking the main thread, and once SlowDude is finished proceed further.
Well, I think, Async Programming is a great thing, and will make our life a lot easier when it comes to Multithreading problems.

WPF Dispatcher

Dispatcher
Windows presentation foundation (WPF) has come up with extensive support for threading. Here I would like to share my experience with threading in WPF.Basically on what situation I have preferred to go with WPF Dispatcher with a code sample.
Define the problem:
We have a requirement in our application that need a mechanism to respond to user and system input such as mouse clicks, key presses, and system events basically having business logic in all these actions also there was a LDAP call to populate the users and cache it and we are making some WCF service call as well to the DB, these operations are going to take time and from the UI the user cannot do any operations till this complete. Not sounds good right. Yes we need to avoid this delay experience to the user while doing all these time consuming business operations.
Technical Solution:
Well , I think from the defanition it is clear that we are not going to address some application specific issue and this might be alredy addressed by any one who come across development of enterprise applications. We have addressed these issues using WPF Dispatcher.Thanks for Microsoft for introducing such a simple way of addressing this issue.
Working with Dispatcher
WPF applications start their lives with two threads: 1) the UI thread which updates the windows, controls, and visual elements of your app, and 2) the BackgroundWorker threads waiting to help you perform the heavy lifting. The ideal approach is illustrated in the very simple diagram below. The UI thread queues work items inside an object called a Dispatcher. The Dispatcher selects work items on a priority basis and runs each one to completion. Every UI thread must have at least one Dispatcher and each Dispatcher can execute work items in exactly one thread.
Basically in .net 2.0 one thread cannot access another thread’s objects directly. If a background thread does attempt to update the UI thread directly, an access violation in the form of an exception is thrown. Dispatcher provides the methods Invoke and Begin Invoke, which a background thread can use to schedule tasks on the UI thread and to specify delegates the dispatcher can use to modify the target object. Messages passed to the dispatcher are marked with a priority level and placed in a queue managed by the dispatcher.
Here I am just giving you a sample code for how UI element is getting updated using dispatcher.

public DispacherTestClass()
{
Thread thread = new System.Threading.Thread(new System.Threading.ThreadStart(delegate()DispatcherOperationdispatcher = textBox1.Dispatcher.BeginInvoke(
System.Windows.Threading.
{
textBox1.Text = “Updated Text from Thread”;
}
));
dispatcher.Completed += += new EventHandler(dispatcher_Completed);
}
));
thread.Start();
}
}
void dispatcher_Completed(object sender, EventArgs e)
{
MessageBox.Show(“The textbox has finished being updated!”);
}
Also if we want to do a background process the code is going to be something like this:

Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Render , AsyncLoadCurrentStaffView, true);

And in the delegete we need to show the method that we want to put in dispatcher que.
new AsyncLoadCurrentStaffViewDelegate(LoadCurrentStaffView);

Populating WPF TreeView

This wil help you to populate a Wpf UI control form a complex hielerichal xml file

try
{
//Just a good practice — change the cursor to a
//wait cursor while the nodes populate
this.Cursor = Cursors.Wait;
//First, we’ll load the Xml document
XmlDocument xDoc = new XmlDocument();
xDoc.Load(dlg.FileName);
//Now, clear out the treeview,
//and add the first (root) node
myTreeView.Items.Clear();
TreeViewItem nodeToAdd = new TreeViewItem();
nodeToAdd.Header = xDoc.DocumentElement.Name;
myTreeView.Items.Add(nodeToAdd);
TreeViewItem tNode = new TreeViewItem();
tNode = (TreeViewItem)myTreeView.Items[0];
//We make a call to addTreeNode,
//where we’ll add all of our nodes
addTreeNode(xDoc.DocumentElement, tNode);
foreach (TreeViewItem item in myTreeView.Items)
{
item.IsExpanded = true;
}
this.Cursor = Cursors.Arrow;
}
catch
{
throw;
}

WPF WebBrowser Control

WPF comes with a ready to use WebBrowser control, which allows you to host a complete web browser within your application. The WebBrowser control is really just a shell around an ActiveX version of Internet Explorer, but since this is an integrated part of Windows, your application should work on all Windows machines without requiring the installation of additional components.
This was based on some requirement from my current project where we have to deal with web browser from our Desktop application which was developed on WPF. Now Lets see some code samples.

<Window x:Class="WpfTutorialSamples.Misc_controls.WebBrowserControlSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="WebBrowserControlSample" Height="300" Width="450">
    <Window.CommandBindings>
        <CommandBinding Command="NavigationCommands.BrowseBack" CanExecute="BrowseBack_CanExecute" Executed="BrowseBack_Executed" />
        <CommandBinding Command="NavigationCommands.BrowseForward" CanExecute="BrowseForward_CanExecute" Executed="BrowseForward_Executed" />
        <CommandBinding Command="NavigationCommands.GoToPage" CanExecute="GoToPage_CanExecute" Executed="GoToPage_Executed" />
    </Window.CommandBindings>
    <DockPanel>
        <ToolBar DockPanel.Dock="Top">
            <Button Command="NavigationCommands.BrowseBack">
                <Image Source="/WpfTutorialSamples;component/Images/arrow_left.png" Width="16" Height="16" />
            </Button>
            <Button Command="NavigationCommands.BrowseForward">
                <Image Source="/WpfTutorialSamples;component/Images/arrow_right.png" Width="16" Height="16" />
            </Button>
            <Separator />
            <TextBox Name="txtUrl" Width="300" KeyUp="txtUrl_KeyUp" />
            <Button Command="NavigationCommands.GoToPage">
                <Image Source="/WpfTutorialSamples;component/Images/world_go.png" Width="16" Height="16" />
            </Button>
        </ToolBar>
        <WebBrowser Name="wbSample" Navigating="wbSample_Navigating"></WebBrowser>
    </DockPanel>
</Window>
namespace WpfTutorialSamples.Misc_controls
{
        public partial class WebBrowserControlSample : Window
        {
                public WebBrowserControlSample()
                {
                        InitializeComponent();
                        wbSample.Navigate("http://www.wpf-tutorial.com");
                }

                private void txtUrl_KeyUp(object sender, KeyEventArgs e)
                {
                        if(e.Key == Key.Enter)
                                wbSample.Navigate(txtUrl.Text);
                }

                private void wbSample_Navigating(object sender, System.Windows.Navigation.NavigatingCancelEventArgs e)
                {
                        txtUrl.Text = e.Uri.OriginalString;
                }

                private void BrowseBack_CanExecute(object sender, CanExecuteRoutedEventArgs e)
                {
                        e.CanExecute = ((wbSample != null) && (wbSample.CanGoBack));
                }

                private void BrowseBack_Executed(object sender, ExecutedRoutedEventArgs e)
                {
                        wbSample.GoBack();
                }

                private void BrowseForward_CanExecute(object sender, CanExecuteRoutedEventArgs e)
                {
                        e.CanExecute = ((wbSample != null) && (wbSample.CanGoForward));
                }

                private void BrowseForward_Executed(object sender, ExecutedRoutedEventArgs e)
                {
                        wbSample.GoForward();
                }

                private void GoToPage_CanExecute(object sender, CanExecuteRoutedEventArgs e)
                {
                        e.CanExecute = true;
                }

                private void GoToPage_Executed(object sender, ExecutedRoutedEventArgs e)
                {
                        wbSample.Navigate(txtUrl.Text);
                }

        }
}

As you can see, hosting and using a complete webbrowser inside of your application becomes very easy with the WebBrowser control. However, you should be aware that the WPF version of WebBrowser is a bit limited when compared to the WinForms version, but for basic usage and navigation, it works fine.

Dependency property

Windows Presentation Foundation (WPF) provides a set of services that can be used to extend the functionality of a common language runtime (CLR) property. Collectively, these services are typically referred to as the WPF property system. A property that is backed by the WPF property system is known as a dependency property.
To be more clear this is same as .NET normal property system, regardless it can hold default value with built in validation sytem.
Intrduction of dependency property, Microsoft has achieved following things.
Value Inheritance
Nothing but the ability of a .NET element to inherit the value. If no local value is set, the dependency property navigates up the logical tree until it finds a value.to be more clear I have root element and have 5 text box on that, and if i say the font defanition on root level all text box will take up that font, unless it is not defined at text box lev el.
Reduced memmory
Yes.It is going to save lot of memory.For example I am defining a button, it has round about 100 properties asssociated with this.Dependency property enable us not to define this 100 properties at element level as it has the capability of inherit the value from parent levels.
Change notification
Dependency properties have a built-in change notification mechanism.