Showing posts with label c#. Show all posts
Showing posts with label c#. Show all posts

Multilanguage applications with C# with database support


As i wrote in an earlier post, the best way to realize a multilanguage application is to get translated text from a database.
This because even if you know 2 or 3 languages, you should be able to sell the application worldwide without even care on what language it is realized.
I think that one of the best database to use for translations is MS Access, because every translator has an office suite installed on his PC, and for him makes no difference translate on Excel or Access, but if you ask him to translate your sentences on "a random SQL data viewer", it can be a pain.
To support multilanguage in my apps i use a method that, given the name of control, returns a string containing the translated text, like:
lblSample.Content = Translation.GetString("lblSample");
The reference to the culture is contained inside Settings, and that's where i modify my language preferences, so when i load the program i know automatically what language i should use.
You can find the link for a working example at the bottom of the page.

To realize a multilanguage selection you need:
- a listbox containing the list of languages,
- an "Apply" button
Features:
- The listbox should automatically detect the new languages
- The application should change not only the texts, but also date/time format, right to left writing and so on.

1#: Create a database file with access like in the sample and add it to the project:

2#: Download the translation class from
here
and paste it in your project,
or you can download the class with the working sample here:
http://www.megaupload.com/?d=H5ISA83P

3#: Add the current culture field on "Settings": this field will be used on all the project to set the national preferences.

4#: Customize the translation class modifying the namespace and the table rererences, if you modified them.
using ChangeLanguage.Properties; // modify the namespace with your project name
[...]
//connection string
        private static DatabaseResourceManager databaseResourceManager = new DatabaseResourceManager(settings.translationsConnectionString);    // here the connection string is declared inside settings; you can declare your own here.
[...]
OleDbCommand command = new OleDbCommand("Select * From Translations"); // Here there is the reference to table name
[...]
command.CommandText = "SELECT [key], [" + language + "] " + "FROM Translations"; // Here there is another reference to table name

5#: Create the GUI like in the example:
if you use xaml you can use this code:
    
        
        
        

6# Then in the main window you can write methods to fill the language comboBox
        /// 
 Detects languages in database and fill the listbox 
        private void LoadCmbItems()
        {
            try
            {
                List cultureList = Translations.GetCultureList();
                listLanguages.ItemsSource = cultureList;
                listLanguages.SelectedItem = settings.currentCulture;
                Date = DateTime.Now;
            }
            catch (Exception exc)
            {
                MessageBox.Show(exc.Message, "Language Database error", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }
and to load / change texts (but usually i do this only on the launch of application)
        private void SetTextsInCurrentLanguage()
        {
            this.Language = XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.IetfLanguageTag);
            LoadCmbItems();
            lblLanguages.Content = Translations.GetString("lblLanguages");
            btnApply.Content = Translations.GetString("btnApply");
            btnButton.Content = Translations.GetString("btnButton");
            lblLabel.Content = Translations.GetString("lblLabel");
            lblDateTime.Content = Translations.GetString("lblDateTime");
        }
You can see that it's really simple to extract translation with this method, it's just needed that you pass the name of the control to the method GetString to receice the translated Content.

7#: Once you wrote all translations, you can update the constructor of the main window to load the localized language and settings:
            Thread.CurrentThread.CurrentCulture = settings.currentCulture;
            Thread.CurrentThread.CurrentUICulture = settings.currentCulture;
            this.DataContext = this;         

            InitializeComponent();

            SetTextsInCurrentLanguage();          
and also create the button "Apply", that basically changes the settings (and in the example refresh the GUI also) :
        private void btnApply_Click(object sender, RoutedEventArgs e)
        {
            settings.currentCulture = (CultureInfo)listLanguages.SelectedItem;
            Thread.CurrentThread.CurrentCulture = settings.currentCulture;  //not so good to see... just to explain how it works
            Thread.CurrentThread.CurrentUICulture = settings.currentCulture;//you should force the user to re-initialize the program
            SetTextsInCurrentLanguage();
        }

You can download the full example here:
http://mesta-automation.com/Downloads/changeLanguage.rar
and read the full documentation here:
http://en.csharp-online.net/Localization_Like_the_Pros

Disclaimer
The sample code described herein is provided on an "as is" basis, without warranty of any kind, to the fullest extent permitted by law. Mestaa.blogspot.com does not warrant or guarantee the individual success developers may have in implementing the sample code on their development platforms or in using their own Web server configurations.

WPF User Controls: 7 Segment Display

7 segment displays is one of the best way to show present values in industrial programs. Operators are used to see numbers and values with  7 segment led characters, and if the operator feels comfortable with what he sees, he works better and in a more correct way.
So it's our work to make them feeling "at home" with the graphic of our programs.
To make a 7 Segment Led it's just a question of adding a custom font.
The one that i like more is NI7SEG (you can download it from here: ni7seg) or google it adding a .ttf at the end.
The code to add a Custom Font is pretty simple:

        /7SegmentLed;Component/Fonts/#NI7Seg
        
where fontfamily refers to /nameofproject;Component/font_folder/name_of_font (to be seen inside the file, not the name of the ttf file).

Then you can just create a label and apply the style:

A sample program can be found here:
http://www.mesta-automation.com/Downloads/7segmentled.rar

HMI Controls for WPF: Led (and a tutorial on WPF User Control)

You can downlaod the source code with sample here: http://www.mesta-automation.com/Downloads/Led%20Wpf.rar

Every Scada system has his own framework that contains a lot of graphic objects, from gauges to charts, that can be controlled directly by some Tags or variables.
Unfortunately .Net doesn't come with this objects, so we have to create them.
In this sample i show how to create a simple graphical Led.

Create a new Control Library (File -> New -> Project -> WPF User Control Library),
then create a new project to test the control( to test and show how to use the control).
After the creation of this 2 projects, set the test project as startup project and add as reference the  control library.
Now we are ready to start creating the graphic part.

Basically a led can be drawn as a Border object that inside it contains a color, and his background is of another color.
This is the code for the graphic part
<Grid x:Name="gridBigLed" >
        <Border x:Name="border1" BorderThickness="6" Width="{Binding ActualHeight, ElementName=gridBigLed, Mode=OneWay}" CornerRadius="{Binding ActualWidth, ElementName=gridBigLed, Mode=OneWay}">
            <Border.Background>
                <RadialGradientBrush >
                    <GradientStop Color="White"/>
                    <GradientStop x:Name="backgroundColor" Color="Red" Offset="0.835"/>
                </RadialGradientBrush>
            </Border.Background>
            <Border.BorderBrush>
                <RadialGradientBrush>
                    <GradientStop Color="#FF020202" Offset="0.383"/>
                    <GradientStop Color="#FFE4E4E4" Offset="1"/>
                </RadialGradientBrush>
            </Border.BorderBrush>
        </Border>
    </Grid>


We bind the height of the border to the height of the grid, so we can resize the control when developing our application.
Corner radius is in binding with width too, to be sure that the border will be always circular.
For the background color you can use wathever you like. I used a radial gradient with Red(Off state) and White , and i will change it with green and  white (On state) depending on the state of a property. That's why I gave the name "backgroundColor" on the red GradientStop.

To give properties to a UserControl we must use Dependency Properties.
We will give 3 properties to the user control:
- bool IsActive
- Color ColorOn (color when IsActive is true)
- Color ColorOff (color when IsActive is false)

The declaration is the following:

/// <summary>Dependency property to Get/Set the current IsActive (True/False)</summary>
        public static readonly DependencyProperty IsActiveProperty =
            DependencyProperty.Register("IsActive", typeof(bool), typeof(Led),// null);
                new PropertyMetadata(new PropertyChangedCallback(Led.IsActivePropertyChanced)));

        /// <summary>Dependency property to Get/Set Color when IsActive is true</summary>
        public static readonly DependencyProperty ColorOnProperty =
            DependencyProperty.Register("ColorOn", typeof(Color), typeof(Led), //null);
                new PropertyMetadata(Colors.Green,new PropertyChangedCallback(Led.OnColorOnPropertyChanged)));

        /// <summary>Dependency property to Get/Set Color when IsActive is false</summary>
        public static readonly DependencyProperty ColorOffProperty =
            DependencyProperty.Register("ColorOff", typeof(Color), typeof(Led),// null);
                new PropertyMetadata(Colors.Red,new PropertyChangedCallback(Led.OnColorOffPropertyChanged)));

        /// <summary>Gets/Sets Value</summary>
        public bool IsActive
        {
            get { return (bool)GetValue(IsActiveProperty); }
            set 
            {
                SetValue(IsActiveProperty, value);
            }
        }

        /// <summary>Gets/Sets Color when led is True</summary>
        public Color ColorOn
        {
            get
            {
                return (Color)GetValue(ColorOnProperty);
            }
            set
            {
                SetValue(ColorOnProperty, value);
            }
        }

        /// <summary>Gets/Sets Color when led is False</summary>
        public Color ColorOff
        {
            get
            {
                return (Color)GetValue(ColorOffProperty);
            }
            set
            {
                SetValue(ColorOffProperty, value);
            }
        }

Now there is a lot to talk about dependency properties, but basically:
you can set the starting value when you create the objects (ColorOn starts with Color.Green and ColorOff start with Color.Red)
and you should note that every property has is name written as string in the 1st field of DependencyProperty.Register method.
the properties also access to values contained in dependency properties  by getValue() and SetValue().

Every Dependency Property should have is own method when it changes. Those methods describe the behaviour of our object, basically a change of IsActive should modify the color of the border and if i change a color at runtime, depending on the state, it should refresh the color instantly.
In this case i wrote the following methods:

private static void IsActivePropertyChanced(DependencyObject d, DependencyPropertyChangedEventArgs e) 
        {
            Led led = (Led)d;
            if ((bool)e.NewValue)
                led.backgroundColor.Color = led.ColorOn;
            else
                led.backgroundColor.Color = led.ColorOff;
        }

        private static void OnColorOnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            Led led = (Led)d;
            led.ColorOn = (Color)e.NewValue;
            if (led.IsActive)
                led.backgroundColor.Color = led.ColorOn;
            else
                led.backgroundColor.Color = led.ColorOff;
        }

        private static void OnColorOffPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            Led led = (Led)d;
            led.ColorOff = (Color)e.NewValue;
            if (led.IsActive)
                led.backgroundColor.Color = led.ColorOn;
            else
                led.backgroundColor.Color = led.ColorOff;
        }

Note that every method is static and it access to the user control property by casting the dependencyobject d.

As for the constructor, i wrote a refresh depending on what color it's set.

public Led()
{
   InitializeComponent();
   if (this.IsActive)
       this.backgroundColor.Color = ColorOn;
   else
       this.backgroundColor.Color = ColorOff;       
}


In this way our control should work.

Now to test we should try it with and without databinding.
This is the test that i wrote:

<Window x:Class="LedTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:uc="clr-namespace:LedControl;assembly=LedControl"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="10"/>
            <RowDefinition Height="Auto" />
            <RowDefinition />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <uc:Led Name="led1" Height="60" Width="60" IsActive="False" Flashing="False" FlashingPeriod="500"  />
        <TextBlock Grid.Column="1">Led without binding</TextBlock>
        <Button Name="btnChange"  Grid.Column="2"  Content="Change" Click="btnChange_Click" />
        <uc:Led Name="led2" Grid.Row="2" Height="60" Width="60" IsActive="{Binding LedStatus}"  />
        <TextBlock  Grid.Row="2" Grid.Column="1">Led with binding</TextBlock>
        <Button Name="btnChange2"  Grid.Row="2" Grid.Column="2"  Content="Change" Click="btnChange2_Click" />
    </Grid>
</Window>
         


public partial class MainWindow : Window,INotifyPropertyChanged
    {
        bool ledStatus;
        public bool LedStatus
        { get { return ledStatus; } set { ledStatus = value; this.OnPropertyChanged("LedStatus"); } }

        public MainWindow()
        {
            InitializeComponent();
            led2.DataContext = this;
            led1.ColorOn = Colors.Blue;
            led1.ColorOff = Colors.Gray;
        }

        private void btnChange_Click(object sender, RoutedEventArgs e)
        {
            led1.IsActive = !led1.IsActive;
        }

        private void btnChange2_Click(object sender, RoutedEventArgs e)
        {
            LedStatus = !LedStatus;
        }


        #region INotifyPropertyChanged members

        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                this.PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
        }

        #endregion  

The 1st button test the led by changing the color from codebehind, the second test it in binding with a property contained (in this case) in the mainwindow directly.

Playing with Blend and adding more Dependency Properties will give even a better result.

Sample App is here: http://www.mesta-automation.com/Downloads/Led%20Wpf.rar

HMI Controls for Winforms: Gauge

Even if i don't like to talk about Winforms, i found a good gauge and i used for 1-2 projects:

The main page for this control and the discussion is here:
http://www.codeproject.com/KB/miscctrl/ThermometerControl.aspx
I add a project for download so you can check the source code and how to use this(it's really simple).

http://www.megaupload.com/?d=TVK7D9M9 

HMI Controls for WPF: Gauge

[Check the updated post here: http://www.mesta-automation.com/wpf-gauge-with-samples/]

Most of times the Gauge indicator is used in HMI projects to visualize Speed - Pressure - Temperatures and so on.
I also prefere using Gause against other tipes of controls such as thermometers, bar graph and others, becuase the measure it's clear and the minimum, maximum and alarm threshold are evidents.
In WPF there are 2 kind of free gauges with free source code:
1) http://wpfgauge.codeplex.com/


this is a free gauge that has no animations (and it can be good ) but it's under the LGPL license, so this means that the code using this gauge must be GPL - licensed.

2) http://www.codeproject.com/KB/silverlight/circulargaugecontrol.aspx?msg=3745697#xx3745697xx
This one is the one that i prefere. It's BSD License (so you can use it basically everywhere) and it is for both Silverlight and WPF.
It's not autosizing and that's a pity, and to dimension it you have to play with some controls.
But anyway it's a great control with a threshold indicator and easy parameters to play around.
It's easy to change colors and sizes of scale and numbers, so it can become a manomether, a thermometer and a tachimeter depending on what application you are working on.

The project can be downloaded from the original site or here:

http://www.megaupload.com/?d=5TMUYC9A


WPF Control: Listbox of checkbox with Search google-like

One thing that i like of WPF is the possibility of making easy-to-use controls to manage data.
A control that i use a lot of times to filter dataviews, charts, get queryes parameters and so on is a listbox of checkbox.
This isn't that special, but with ICollectionView and the possibility of having a fast way to filter results like the search box in google.com it become a really powerful tool.

I invite you to download the demo (link at the bottom of this page) to understand better.

Let's start from an example:
I have an observable collection of "Fruits", objects that contain a property "Name" and a property "Show" that indicates if the object has to be visualized or filtered.

To filter this collection i can use the ICollectionView, that permits to filter a collection and has a method Refresh() that reload the collection with the filter parameters.

So in the properties i add:
 class MyFruitCollection : ObservableCollection
    {

private ICollectionView filteredCollection;
public ICollectionView FilteredCollection { get { return filteredCollection; } }


and the filter string:

private string filter = "";
        public string Filter
        {
            get { return this.filter.ToUpperInvariant(); }
            set
            {
                if (this.filter != value)
                {
                    this.filter = value;
                    this.filteredCollection.Refresh(); //
Notice that i call Refresh() at every change of filter
                }
            }
        }


In the constructor of my collection i add some fruits(just for example) and i load the ICollectionView datasource:

        public MyFruitCollection()
        {
            this.Add(new MyFruit("Orange"));
            ...
            this.Add(new MyFruit("Watermelon"));

            this.filteredCollection = CollectionViewSource.GetDefaultView(this);
            this.filteredCollection.Filter = ContainsFilter;
        }

Then i set the filters on this method:

private bool ContainsFilter(object item)
        {
            var fruit = item as MyFruit;
            if (fruit == null)  //check if fruit is null
            {
                return false;
            }
            if (string.IsNullOrEmpty(this.Filter)) //check if search box is empty or null
            {
                return true; //show all items if there is no text in the search textbox
            }
            if (fruit.Name.ToUpperInvariant().Contains(this.Filter))
//checks if fruit.name contains the search text
            {
                return true;
            }
            return false; //if it doesn't contain anything don't show the item
        }


 Xaml is pretty simple, as usual it's all about databinding:

And this is the code behind:

    public partial class MainWindow : Window
    {

MyFruitCollection fruitCollection = new MyFruitCollection();

        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = fruitCollection;
//notice that all the application is in binding
        }

...
}

The resul is pretty cool and it makes apps a lot more confortable, just try yourself :)
Download the example here:
http://mesta-automation.com/Downloads/Selection%20control.rar

C# and Siemens PLC: LIBNODAVE

Usually i work with Allen Bradley PLCs, but most of PLC's programmers use Siemens PLC.
One thing that i really appreciate of Siemens is the possibility to connect a PC to PLC in a total FREE way, using LIBNODAVE.

Libnodave is a free library compiled in some programming languages (C, C++, C# etc...) that permit to exchange data with Siemens PLC for free and to embed the driver in  the program.
You just have to add as reference the libnodave.Net.dll and start to read and write data using the simple samples inside the docs.
The main page of libnodave is here:
http://libnodave.sourceforge.net/
and the download page of the full package is here:
http://sourceforge.net/projects/libnodave/

At the moment they have developed the version 0.8.4.5, but the project is still alive and healty.
There is also an help forum here:
http://sourceforge.net/projects/libnodave/forums/forum/205657
that can help who is having troubles while writing is first driver.

As usual, once you wrote how to communicate with the PLC, you can fire an event of "DataChanged" and use it to update your WPF UI with databinding, as seen in the previous posts.

UPDATE: You can find a project contaning some communication samples on http://siemensplctoolboxlib.codeplex.com/ . It's one layer above  libnodave and it's possible to download the the source code.

WPF and OPC: a full sample project with RSLinx and databinding

Now that i wrote about databinding, pages and so on, i publish an example on how to connect real time values readed from a PLC (in this case an Allen Bradley PLC, but it can be anyone), update an object collection with this values, and then display them on different pages.

As usual i have my 2 tanks and i want to read what liquid is inside every tank (defined as 16bit integer).
1st tank word is N7:0, second is N7:1
For each tank there is a button that changes its content(writing the PLC word).

This is the new code to analyze: i have 2 buttons that writes the words on PLC, then i have the callback where i read values in PLC, cast them and update my objects.
This objects are defined in the OPC Client class and they are defined as "public"  because i want to access their properties from every window that needs to display real time values or to control them.


This is the MainWindow, where the program begin and where i create the opcclient object as static.
To access to it's properties i just need to bind UI items by databinding.




To access the properties of objects in another window or page, i do like in this example.

And this is the final result

This is how the setup for PLC OPC Server, that should be called as [UNTITLED_2]


Hope it's helpful.
Full solution here:

http://www.mesta-automation.com/Downloads/opc%20sample%202.rar

Previus post describe more in details what's used in this example, if you're interested.

OPC Client c# .Net Sample (RSLinx OPC server)

Hi, a big problem about connecting PLC to PC is the "from where should i start?".
And that's why i suppose people choose commercial SCADA instead of .Net (they already has drivers and so on).
Well, if it was for winforms, i would agree that winforms sucks, they got a lot of bugs and so on, so i would choose a commercial SCADA too.
But since WPF and Silverlight was released, .Net is really more more powerful and beautiful, the code became easier with the binding system and industrial PCs + OPC servers cost always less (and sometimes it's possible to find free drivers).

This post is an example of communication with RSLinx OPC Server (but i use OPC Foundation libraries so the process is the same for every OPC server).


So let's strart by adding a reference to the OPC Foundation dlls:
- OpcNetApi.Com.dll
- OpcNetApi.dll
- OpcNetApi.Xml.dll

Then create Items that are shared for the all the form (or the project)
Then create a button to connect (or just place the code after InitializeComponent(); if you want to autoconnect when the program starts)
Set the URL (in this sample there is the one of RSLinx) then add a group, add some items with theyr connection string, set the update time and the callback for the items that you want to read, then set a group for writings.


 This is the sample callback where i assign values that i read to a custom object.
Remember that the GUI and the OPC client runs on two different threads, so it's needed to use anonymous method for this (just use like is written in the sample).
With WPF and INotifyPropertyChanged it's not needed this.
You can just bind all your objects to the GUI items property, and this is really amazing and simple.
 This is the way that i found to write a single word, basically i create a new one, i check if in the write group there is already one of them, else i add it.
 Writing was always a problem for me, but when i found this way, i got all i needed

This is a sample of how i write from a button reading a textbox


IMPORTANT UPDATE: This code is written on a Micrologix / SLC platform and it reads only integer values, so when i read a value it's supposed to be a 16-bit word: that's why i cast it to (short). Remember that if you read a REAL value (F8:0 for example) you sould cast it to float and if you read from Controllogix or CompactLogix, you have to convert it to (int) because they are 32-bit words.

This is the complete solution:

http://www.mesta-automation.com/Downloads/OPC%20Client.rar

This is another link for a Twincat OPC Server, that is similar to the RSLinx.
http://infosys.beckhoff.com/content/1033/tcopcserver/html/sample1_netapi.htm?id=18186

UPDATE: i wrote a recent post here where i wrote a full sample with WPF and an OPC client in c#. watch it here: http://mestaa.blogspot.com/2010/12/wpf-and-opc-full-sample-project-with.html

[UPDATE #2]: i made a video that explains how to use the code provided: check it here: http://www.mesta-automation.com/opc-client-with-c-an-how-to-video/