Saturday, September 19, 2015

Entity Framework cannot get Column Information for Complex Types result

This link saves me:

http://stackoverflow.com/questions/7128747/ef4-the-selected-stored-procedure-returns-no-columns

I have a stored procedure that joins multiple tables, performs queries and returns a Complex Types result. When setting this up in EF designer, EF cannot detect the columns returned from the stored procedure. As Ladislav pointed out, EF needs to execute the stored procedure to actually get the column information. I choose the second solution. I hack my stored procedure to include SET FTMONLY OFF. The first solution works too until someone tries to update the model from database or if the stored procedure is adjusted to return different columns.

The problem with this, well actually the problem with my stored procedure is that there's no default parameter value specified. EF executes my stored procedure with NULL parameter resulting in error as the stored procedure expects non NULL parameter value to be passed in, so I still ended up with no column information. I finally hack my stored procedure as follows:

IF @param1 IS NULL AND @param2 IS NULL
BEGIN
   SET FTMONLY OFF
   SET @param1 = 0
   SET @param2 = '1900-01-01'
END

@param1 is an identifier and @param2 is a date. Setting identifier to 0 and date to something way in the past guarantee that there's no result returned but that's okay since we're only interested in the column information.

Saturday, August 15, 2015

Embed SSRS Report Into WPF Application Without ReportViewer

When you google how to embed SSRS report into WPF application, chances are you'd come across this page at least once:

Walkthrough: Using ReportViewer in a WPF Application

But what if you don't want to use any of Windows Form controls? ReportViewer is Windows Form control.

There is WPF WebBrowser control we potentially could use, but it doesn't have a ready built-in attribute that we could simply set an URL to, so there's an extra step needed before we can use it. An attached property will do this for us.

    public static class WebBrowserHelper
    {
        public static readonly DependencyProperty WebAddressProperty = DependencyProperty.RegisterAttached(
            "WebAddress", 
            typeof (string), 
            typeof (WebBrowserHelper), 
            new PropertyMetadata(OnWebAddressChanged));

        public static string GetWebAddress(DependencyObject dependencyObject)
        {
            return (string) dependencyObject.GetValue(WebAddressProperty);
        }

        public static void SetWebAddress(DependencyObject dependencyObject, string value)
        {
            dependencyObject.SetValue(WebAddressProperty, value);
        }

        private static void OnWebAddressChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            WebBrowser browser = d as WebBrowser;
            if (browser != null && e.NewValue != null)
            {
                string url = e.NewValue.ToString();
                browser.Navigate(url);
            }
        }
    }

To use it, simply call the attached property from WebBrowser and bind it to the SSRS URL in the ViewModel.


<UserControl x:Class="Views.WebBrowserView"
             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:local="clr-namespace:Views.Helpers"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">   
    <Grid>
        <WebBrowser local:WebBrowserHelper.WebAddress="{Binding Path=SsrsUrl}" />
    </Grid>
</UserControl>

public class ViewModel
{
    public string SsrsUrl { get; set; }
}

And we're pretty much done.

Sunday, July 12, 2015

SQL Custom ORDER BY Multiple Columns

There're a lot of examples how to do custom ordering by one or multiple columns, but not for this particular case I'm working on. I need to do custom ordering based on a combination of static values across two tables.

   -------------------   ---------------
   | AssetClass      |   | AccountType |
   -------------------   ---------------
   | Equity          |   | FUT         |
   | Private Equity  |   | UIV         |
   | Credit          |   | NUIV        |
   | Macro           |   ---------------
   | Government Bond |
   -------------------

The query result should first be ordered by the AssetClass and then by the AccountType in the exact same order as shown above. Notice that neither is ordered alphabetically. An example of the result would look like something like this:

   ---------------------------------
   | AssetClass      | AccountType |
   ---------------------------------
   | Equity          | FUT         |        
   | Equity          | FUT         |
   | Equity          | FUT         |
   | Equity          | UIV         |
   | Equity          | UIV         |
   | Equity          | NUIV        |
   | Equity          | NUIV        |
   | Equity          | NUIV        |
   | Equity          | NUIV        |
   | Private Equity  | FUT         |
   | Private Equity  | FUT         |
   | Private Equity  | UIV         |
   | Private Equity  | UIV         |
   | Private Equity  | NUIV        |
   | Private Equity  | NUIV        |
   | ...             | ...         |
   | ...             | ...         |
   | ...             | ...         |
   | Government Bond | UIV         | 
   | Government Bond | UIV         |  
   | Government Bond | NUIV        |  
   | Government Bond | NUIV        |  
   | Government Bond | NUIV        |  
   ---------------------------------      
The ORDER BY statement is ugly but hey it does the job.
ORDER BY
    CASE [AssetClass]
        WHEN 'Equity' THEN
            CASE [AccountType]
                WHEN 'FUT' THEN 1
                WHEN 'UIV' THEN 2
                WHEN 'NUIV' THEN 3
                ELSE 4
            END
        WHEN 'Private Equity' THEN
            CASE [AccountType]
                WHEN 'FUT' THEN 5
                WHEN 'UIV' THEN 6
                WHEN 'NUIV' THEN 7
                ELSE 8
            END
        ...
        ...
        WHEN 'Government Bond' THEN
            CASE [AccountType]
                WHEN 'FUT' THEN 17
                WHEN 'UIV' THEN 18
                WHEN 'NUIV' THEN 19
                ELSE 20
            END
    END

Friday, June 12, 2015

SSRS Multi Value Parameter And Stored Procedure

I'm always struggling when it comes to dealing with SSRS multi value parameter. There're basically two ways of doing this:
1) Use SRRS Filter
2) Use good old SQL

I definitely prefer the first approach because it's so much simpler. All we need is a Dataset which returns result set for all possible values of the multi-value parameter and then we filter it based on the selected items. Let's say we have a Dataset called Companies with field Name. Steps to filter:

  1. Create a multi value parameter, let's call it @Company and suppose it contains the following items: AAA, BBB, CCC, which are the distinct names in field Name of the Dataset Companies.
  2. Click on Dataset Properties and select Filters in the left-hand pane
  3. In the Expression drop-down list, select Name as the field to filter
  4. In the Operator drop-down list box, select the In operator
  5. In the Value box, type in [@Company]
And you're done!

Now the second approach will involve creating a Stored Procedure that takes in one string argument, which contains the values of the selected multi-value parameter all joined together with a delimiter that we will need to parse in our Stored Procedure to be able to use it in the SQL IN clause. Using the same example as before, this string argument is something like: "AAA,BBB,CCC". In the SSRS report, on the Parameters of the query definition, we will need to set the parameter value to something like:

    =Join(Parameters!Company.Value,",")
This method is definitely more complicated. We will need to write a SQL string split function in our Stored Procedure taking into account the possibility that the delimiter is not always going to be a comma and whether we need to handle entry with white space in between.

Saturday, May 30, 2015

Windows Form MVVM databinding

I inherited a complex Windows Form UserControl that contains a DataGridView showing a matrix data structure like this.

The code behind takes care of the generation of the headers and cell values. It also takes care of the cell color scheme based on the value of the cell.

Because of the complexity and the fact that there's no out-of-the-box DataGridView implementation for WPF application, I decided to reuse this Windows Form UserControl in a WPF application I was working on. The problem is that Windows Form does not support data binding in WPF MVVM context. We will need to do the plumbing ourselves to be able to use the data binding functionality. One way to do this is as follows:

  1. Wrap the Windows Form UserControl in a WPF UserControl by using WindowsFormsHost
  2. Create DependencyProperty in this WPF UserControl, which we can use to bind to a viewmodel
  3. Use PropertyChangedCallback to modify property or state in the DataGridView control
  4. Use events in the DataGridView control to return property or state back to the DependencyProperty in the WPF UserControl

I'm posting a simple version of the original source code to illustrate this. Let's start with the business objects.

The Business Objects

    public class TenorStrikeRate
    {
        public TenorStrikeRate(string tenor, double strike, double rate)
        {
            Tenor = tenor;
            Strike = strike;
            Rate = rate;
        }

        public string Tenor { get; set; }

        public double Strike { get; set; }

        public double Rate { get; set; }
    }
    public class TenorStrikeRates : IEnumerable<TenorStrikeRate>
    {
        private readonly SortedList<Tuple<string, double>, TenorStrikeRate> internalData;

        public TenorStrikeRates()
        {
            internalData = new SortedList<Tuple<string, double>, TenorStrikeRate>();
        }

        public List<string> UniqueSortedTenors
        {
            get { return internalData.Values.Select(x => x.Tenor).Distinct().ToList(); }
        }

        public List<double> UniqueSortedStrikes
        {
            get { return internalData.Values.Select(x => x.Strike).Distinct().ToList(); }
        }

        public void Add(TenorStrikeRate toBeAddedItem)
        {
            Tuple<string, double> key = new Tuple<string, double>(toBeAddedItem.Tenor, toBeAddedItem.Strike);
            if (internalData.ContainsKey(key))
            {
                internalData.Remove(key);
            }

            internalData.Add(key, toBeAddedItem);
        }

        public TenorStrikeRate Find(string tenor, double strike)
        {
            return internalData.Values.FirstOrDefault(x => IsTenorEqual(x.Tenor, tenor) && IsDoubleEqual(x.Strike, strike));
        }

        public IEnumerator<TenorStrikeRate> GetEnumerator()
        {
            IEnumerator<TenorStrikeRate> iterator = internalData.Values.GetEnumerator();
            while (iterator.MoveNext())
            {
                yield return iterator.Current;
            }
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj))
                return false;
            if (ReferenceEquals(this, obj))
                return true;
            if (obj.GetType() != typeof(TenorStrikeRates))
                return false;

            TenorStrikeRates other = (TenorStrikeRates)obj;
            return IsAllItemInListEqual(internalData.Values, other.internalData.Values);
        }
        
        private bool IsAllItemInListEqual(IList<TenorStrikeRate> thisList, IList<TenorStrikeRate> otherList)
        {
            bool isEqual = thisList.Count.Equals(otherList.Count);
            for (int index = 0; index < otherList.Count && isEqual; index++)
            {
                TenorStrikeRate thisItem = thisList[index];
                TenorStrikeRate otherItem = otherList[index];
                isEqual = IsTenorEqual(thisItem.Tenor, otherItem.Tenor) 
                    && IsDoubleEqual(thisItem.Strike, otherItem.Strike)
                    && IsDoubleEqual(thisItem.Rate, otherItem.Rate);
            }

            return isEqual;
        }

        private bool IsDoubleEqual(double one, double two)
        {
            if (double.IsNaN(one) && double.IsNaN(two))
            {
                return true;
            }

            return Math.Abs(one - two) < 1e-15;
        }

        private bool IsTenorEqual(string one, string two)
        {
            return one.Equals(two, StringComparison.InvariantCultureIgnoreCase);
        }
    }

The Windows Form UserControl

The Windows Form UserControl contains a DataGridView named "dgv". Set(TenorStrikeRates source) populates the DataGridView. GetDataGridSource() returns the current source state of the DataGridView. In this class we also need to declare a public event to return the current data grid source to the subscribers. A situation where we want to return the current data grid source is when users perform a data grid cell editing operation. We can then hook up this public event to the DataGridView CellEndEdit event which occurs when edit mode stops for the currently selected cell.

    public partial class DataGridViewUc : System.Windows.Forms.UserControl
    {
        public DataGridViewUc()
        {
            InitializeComponent();
        }

        public delegate void ReturnGridSourceEventHandler(TenorStrikeRates currentGridSource);

        public event ReturnGridSourceEventHandler ReturnDataGridSource;

        public void Set(TenorStrikeRates source)
        {
            dgv.Columns.Clear();
            dgv.Rows.Clear();
            if (source != null)
            {
                PopulateColumnHeader(source.UniqueSortedStrikes);
                PopulateRowHeader(source.UniqueSortedTenors);
                PopulateCells(source);
            }
        }

        public TenorStrikeRates GetDataGridSource()
        {
            TenorStrikeRates quotes = new TenorStrikeRates();
            foreach (DataGridViewColumn column in dgv.Columns)
            {
                string columnHeaderValue = column.HeaderText;
                if (columnHeaderValue != null)
                {
                    double strike = ReadStrike(columnHeaderValue);
                    foreach (DataGridViewRow row in dgv.Rows)
                    {
                        object rowHeaderValue = row.HeaderCell.Value;
                        if (rowHeaderValue != null)
                        {
                            string tenor = rowHeaderValue.ToString();
                            object rateValue = row.Cells[column.Name].Value;
                            double rate = rateValue == null ? double.NaN : Convert.ToDouble(rateValue);
                            quotes.Add(new TenorStrikeRate(tenor, strike, rate));
                        }
                    }
                }
            }

            return quotes;
        }

        private void PopulateColumnHeader(List<double> strikes)
        {
            foreach (double strike in strikes)
            {
                string headerText = strike.ToString("P2");
                dgv.Columns.Add(headerText, headerText);
            }
        }

        private void PopulateRowHeader(List<string> tenors)
        {
            int numberOfRows = tenors.Count;
            dgv.Rows.Add(numberOfRows);
            for (int i = 0; i < numberOfRows; i++)
            {
                dgv.Rows[i].HeaderCell.Value = tenors[i];
            }
        }

        private void PopulateCells(TenorStrikeRates quotes)
        {
            List<string> tenors = quotes.UniqueSortedTenors;
            List<double> strikes = quotes.UniqueSortedStrikes;
            for (int rowIdx = 0; rowIdx < tenors.Count; rowIdx++)
            {
                string optionTenor = tenors[rowIdx];
                for (int colIdx = 0; colIdx < strikes.Count; colIdx++)
                {
                    double strike = strikes[colIdx];
                    TenorStrikeRate quote = quotes.Find(optionTenor, strike);
                    if (quote != null)
                    {
                        double rate = quote.Rate;
                        DataGridViewCell cell = dgv.Rows[rowIdx].Cells[colIdx];
                        cell.Value = rate;
                    }
                }
            }
        }
        
        private double ReadStrike(string input)
        {
            string percentSymbol = Thread.CurrentThread.CurrentCulture.NumberFormat.PercentSymbol;
            input = input.Replace(percentSymbol, string.Empty);
            return double.Parse(input, Thread.CurrentThread.CurrentCulture.NumberFormat) / 100;
        }

        private void dgv_CellEndEdit(object sender, DataGridViewCellEventArgs e)
        {
            if (ReturnDataGridSource != null)
            {
                TenorStrikeRates newSource = GetDataGridSource(); 
                ReturnDataGridSource(newSource);
            }
        }
    }

The WPF Host

To be able to bind the DataGridView UserControl to a viewmodel, we will need to wrap it in a WPF UserControl by using WindowsFormsHost. Then we define DependencyProperty GridSource that we can bind to a property in the viewmodel. Next we define PropertyChangedCallback OnGridSourcePropertyChanged, which is called whenever GridSource property changed. In the callback, we pass in the new source to the DataGridView so it can update its display. The WPF UserControl needs to subscribe to the DataGridView's ReturnDataGridSource event to make sure any changes in the DataGridView is propagated to the WPF host layer.

XAML:


<UserControl x:Class="DataGridViewHostedInWpfControl.WpfHost.DataGridViewUcHost"
             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:local="clr-namespace:DataGridViewHostedInWpfControl.WinFormLayer"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    
    <WindowsFormsHost x:Name="MyWinFormsHost">
        <local:DataGridViewUc />
    </WindowsFormsHost>

</UserControl>

Code behind:

    public partial class DataGridViewUcHost : System.Windows.Controls.UserControl
    {
        public static readonly DependencyProperty GridSourceProperty = DependencyProperty.Register(
             "GridSource",
             typeof(TenorStrikeRates),
             typeof(DataGridViewUcHost),
             new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnGridSourcePropertyChanged));

        public TenorStrikeRates GridSource
        {
            get { return (TenorStrikeRates)GetValue(GridSourceProperty); }
            set { SetValue(GridSourceProperty, value); }
        }

        private static DataGridViewUc dgvUc;

        public DataGridViewUcHost()
        {
            InitializeComponent();

            dgvUc = (DataGridViewUc)MyWinFormsHost.Child;
            dgvUc.ReturnDataGridSource += OnReturnDataGridSource;
        }

        private static void OnGridSourcePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            TenorStrikeRates newGridSource = (TenorStrikeRates)e.NewValue;
            TenorStrikeRates currentGridSource = dgvUc.GetDataGridSource();
            if (!currentGridSource.Equals(newGridSource))
            {
                dgvUc.Set(newGridSource);
            }
        }

        private void OnReturnDataGridSource(TenorStrikeRates currentGridSource)
        {
            GridSource = currentGridSource;
        }
    }

The MainWindow

Now let's build a small demo. Create a StackPanel containing the WPF control that hosts our DataGridView UserControl. Add a TextBox to the StackPanel. Everytime we change a value in the data grid, the change will be shown in the TextBox.

XAML:


<Window x:Class="DataGridViewHostedInWpfControl.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:DataGridViewHostedInWpfControl.WpfHost"
        Title="MainWindow" Height="350" Width="525">
    
    <StackPanel>
        <Label Content="Input" />
        <local:DataGridViewUcHost GridSource="{Binding Input}" MinWidth="300" MinHeight="100" Margin="10" />
        <Label Content="Output" />
        <TextBox Text="{Binding Output}" />
    </StackPanel>

</Window>

Code behind:

    public partial class MainWindow : System.Windows.Window
    {
        public MainWindow()
        {
            MainViewModel vm = new MainViewModel();
            DataContext = vm;

            InitializeComponent();

            vm.Input = BuildInitialInput();
        }

        private TenorStrikeRates BuildInitialInput()
        {
            var quotes = new TenorStrikeRates();
            quotes.Add(new TenorStrikeRate("1y", -0.01, 0.01));
            quotes.Add(new TenorStrikeRate("1y", 0, 0.02));
            quotes.Add(new TenorStrikeRate("1y", 0.01, 0.03));
            quotes.Add(new TenorStrikeRate("2y", -0.01, 0.04));
            quotes.Add(new TenorStrikeRate("2y", 0, 0.05));
            quotes.Add(new TenorStrikeRate("2y", 0.01, 0.06));
            return quotes;
        }
    }

ViewModel:

    public class MainViewModel : INotifyPropertyChanged
    {
        private TenorStrikeRates input;
        public TenorStrikeRates Input
        {
            get { return input; }
            set
            {
                input = value;
                OnPropertyChanged("Input");
                Output = BuildOutputValue(value);
            }
        }

        private string output;
        public string Output
        {
            get { return output; }
            set
            {
                output = value;
                OnPropertyChanged("Output");
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        private string BuildOutputValue(TenorStrikeRates tenorStrikeRates)
        {
            string text = string.Empty;
            foreach (TenorStrikeRate item in tenorStrikeRates)
            {
                text = text + string.Format("Tenor: {0}, Strike: {1}, Rate: {2}\n", item.Tenor, item.Strike.ToString("P2"), item.Rate);
            }

            return text;
        }
    }

Source Code

https://github.com/velianarie/DataGridViewHostedInWpfControl

Saturday, April 18, 2015

OpenLink Findur OpenComponents External Plugin

At work we've been trying for the last 2 years to replace our current system with OpenLink Findur. I was involved in integrating our internal pricing library by using their OpenComponents .NET API. It was tough but we successfully delivered that part of the project, so I was out of the project and had been doing other things since then. Around a month ago, I was suddenly asked to take over yet another part of this massive project from a contractor hired to do this as the management didn't want to extend her contract. So that's how I got sucked into this project again T_T.

The part I was asked to take over is a .NET C# Console Application built using OpenLink OpenComponents .NET API. This plugin is attached to Findur End of Day (EOD) workflow and runs at the very end of the workflow. This plugin extracts some of the EOD results and produces xml's needed by a lot of our legacy tools that we don't have time yet to adjust to communicate with Findur. At least not at this phase of the project.

If you're like me, I find debugging extremely important especially when you're pulled out of whatever you're doing, thrown into a massive project and expected to be up and running after 2 hours handover. Well the bad news was that she said it's impossible to debug the plugin. I asked her how she managed to build something quite big (there're more than 5000 lines of codes) without debugging it. She said she put logging lines almost everywhere, pressed F5 and waited until it either crashed (and then checked the log) or finished executing (and then checked the resulting xml's). My first reaction was: Are you kidding me?!? She also said that this plugin could only work when there's only one Findur session running in the application server as users access Findur via Citrix. At this point I had to pinch myself to check whether I was dreaming. Surely something is wrong when you need an extra application server wholly dedicated to test this plugin. It just sounds absurd.

Okay now that I'm done rambling, let's formulate the problems she mentioned and what I did to somehow make it works.

Problem #1: "You cannot debug this external Findur plugin..."


SEHException - External component has thrown an exception

So first thing I did after having all my development environment set up was putting a random breakpoint in the solution and pressing F5. It ran for a couple of seconds and then it stopped at that breakpoint. Hmmm, I thought she said we couldn't debug it? So I pressed F5 again to resume and bang! it threw a 'SEHException - External component has thrown an exception' in:

   Application app = Application.GetInstance();
Ah so this was what she meant by "You cannot debug this external Findur plugin..."

Next thing I did was going to the guy who's responsible for deploying this plugin to a test environment and asked him whether it had ever worked before and how he'd run it. He said it had worked before. At the end of Findur EOD workflow, there's a process that would trigger this plugin. He even demonstrated that it worked by manually double clicking the .exe file. I went back to my desk and double clicked the .exe file in Visual Studio bin\Debug folder. It ran successfully and produced the expected xml's. So it did seem that the contractor was right, we can't debug this plugin.

Being the person that I am, I didn't give up. To be honest I didn't want to take on a project where I'd need to code blindly and invest my time in writing log entries. Besides I wasn't even sure that log entries would help me with coding the logic of extracting data from Findur simulation results. We're talking about lots and lots of Findur Table class inquiries here. I couldn't find anything about this exception on google, nothing related to Findur, so I tried the next best thing: cleaning the solution. It had done the trick in multiple occasions in the past and I was desperate, so why not? And by "cleaning" I meant manually deleting the output files, not using Visual Studio Clean Solution. It refused to delete vshost.exe file as it's in use, obviously because I had the solution still open. Then I thought, "Wait a minute, vshost.exe is a feature in Visual Studio related to debugging and my current problem is related to debugging. Running it by double clicking the .exe works fine." At this point, I just followed my gut instinct, I closed the solution, deleted the vshost.exe, reopened the solution, recompiled and pressed F5. And then the magic happened, it didn't crash on Application.GetInstance(). Hooray!!


Debug stop working after a couple of step-into's

Apparently it's not over yet. Debugging only lasted for approximately 3 step-into's and then it simply refused to stop on any more breakpoint. The yellow line highlighting the current line went away, but it never reached the next line. The solution window title showed "(Running)" and I couldn't do anything but stopped the debugging session and restarted the whole thing. I ended up having to choose my breakpoint very wisely since I only got a limited number of step-into's. Was this what the contractor meant by "You cannot debug this external Findur plugin..."?

Again being the person that I am, I refused to give up. "Choose your breakpoints wisely" lol it even sounds silly. So going back to google search, some people recommended switching off property evaluation and other implicit function calls. This setting can be found in Tools > Options and then select Debuging > General. Find check box Enable property evaluation and other implicit function calls and uncheck it. This, my friends... didn't work.

This worked for me though:
Tools > Import and Export Settings > Reset all settings
If you're reading this because you have the same problem and about to try it out, please please note that you're going to LOSE your Resharper settings (if you're using it) and personalized keyboard shortcuts! So make sure you back up your settings when it asks you to.



Problem #2: "External plugin can only work if there's only one Findur session running..."

Original code:

   Application app = Application.GetInstance();
   Session session = app.Attach();
Application and Session class can be found in Olf.Openrisk.Application namespace. Here we see that we don't tell it to attach to a specific session. No wonder it only worked if there's only one session running. It'll just attach itself to a random session.

Now I want the plugin to attach to a specific Findur database session. If that session is not running, I want the plugin to start it and then attach itself to it. For this purpose, I introduce 3 configuration keys in App.config:

    <add key="DatabaseName" value="Findur_Test" />
    <add key="OlfBinFolder" value="C:\OpenLink\Findur_V14_1_01172015MR_02182015_1037\bin" />
    <add key="OlfParams" value="-olfcfg \\servername\ConfigFiles\TestConfig.olf -u svcAccUser -p 1234567" />
DatabaseName is the name of Findur database session we want to attach our plugin to. OlfBinFolder specifies the location where Findur is installed. There should be an executable master.exe in this bin folder which is the one we use to start Findur. OlfParams specifies the command parameters of master.exe. When you run Findur from the command prompt it reads as follows:
  C:\OpenLink\Findur_V14_1_01172015MR_02182015_1037\bin\master.exe -olfcfg \\servername\ConfigFiles\TestConfig.olf -u svcAccUser -p 1234567

Findur Application class has another Attach method where we can specify a session ID we want to attach to. There can only be one Application instance (because it's a singleton), while we can have multiple Findur sessions running on it.

If we have a Findur session running, we can see the session ID by clicking on the i (information) icon. Unfortunately this session ID changes every time we start a session and there's no way the plugin can access this information without first attaching itself to a running session, so we cannot know beforehand what the session ID is (classic chicken and egg problem isn't it? ;)). Fortunately there's SessionDescriptions property on the Application class which returns all the session ID's running on it. We can iterate through each of these session ID's, attach our plugin to it so that we can ask for the session's database name. When the attached database name is not equal to the database name we want ie. the one we specified in App.config, we detach it and continue with the next session ID and repeat the process until we find the database we want. If we don't find it, return null. Null means that the session we want to attach to is not running and therefore we will start it by running whatever specified in OlfBinFolder and OlfParams.

The adjusted code:

        Application app = Application.GetInstance();
        Session session = GetSession(app);
where:
        private Session GetSession(Application app)
        {     
            string databaseName = ConfigurationManager.AppSettings["DatabaseName"];
            Session session = GetRunningSession(app, databaseName);
            if (session == null)
            {
                string binDir = ConfigurationManager.AppSettings["OlfBinFolder"];
                string parameters = ConfigurationManager.AppSettings["OlfParams"];
                session = app.StartSession(binDir, parameters);
            }

            return session;
        }

        private Session GetRunningSession(Application app, string databaseName)
        {
            IEnumerable<int> sessionIds = app.SessionDescriptions.Select(x => x.Id);
            foreach (int sessionId in sessionIds)
            {
                Session attachedSession = app.Attach(sessionId);
                string attachedDatabaseName = attachedSession.DatabaseName;
                if (attachedDatabaseName != databaseName)
                {
                    app.Detach();
                }
                else
                {
                    return attachedSession;
                }
            }

            return null;
        }

So what is the moral of the story?
* Don't blindly trust what you're told, what does the code say?
* Don't give up and google is your friend ;)

Sunday, April 12, 2015

Annoying Last Empty Row on WPF DataGrid



<Window x:Class="AnnoyingDataGridExtraRow.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"
        Name="ThisWindow">

    <DataGrid ItemsSource="{Binding ElementName=ThisWindow, Path=MyModels}" AutoGenerateColumns="False">
        <DataGrid.Columns>
            <DataGridTextColumn Header="Strings" Binding="{Binding Text}" />
            <DataGridTextColumn Header="Doubles" Binding="{Binding Value}" />
        </DataGrid.Columns>
    </DataGrid>
</Window>

public partial class MainWindow : Window
{
    public MainWindow()
    {
        MyModels = new List<MyModel>
        {
            new MyModel { Text = "AAA", Value = 0.423 },
            new MyModel { Text = "BBB", Value = 0.315 },
            new MyModel { Text = "CCC", Value = 4.422 }
        };

        InitializeComponent();
    }

    public List<MyModel> MyModels { get; set; }
}
public class MyModel
{
    public string Text { get; set; }

    public double Value { get; set; }
}

If we don't specify a constructor, WPF DataGrid will default to an empty constructor, which allow users to add new row to the grid.

If I change MyModel to something like this:

public class MyModel
{
    public MyModel(string text, double value)
    {
        Text = text;
        Value = value;
    }

    public string Text { get; set; }

    public double Value { get; set; }
}

...then that extra row disappears.

If we want to make the DataGrid readonly, make sure we don't specify an empty constructor. Otherwise we need to set CanUsersAddRows to False.

Wednesday, April 1, 2015

WPF DataGrid Dynamic Numeric Formatting

I have a simple WPF DataGrid containing numbers that I want to format dynamically based on the state of 2 other WPF controls:

  • UserControl with 2 buttons: the precision
  • ComboBox: the format specifier


The User Control: Precision Adjuster

XAML:
<UserControl x:Class="DataGridFormatting.PrecisionAdjuster"
             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"
             mc:Ignorable="d"
             d:DesignHeight="50" d:DesignWidth="100">

    <UserControl.Resources>
        <Style TargetType="{x:Type Button}">
            <Setter Property="Width" Value="30" />
            <Setter Property="Height" Value="30" />
            <Setter Property="Margin" Value="3" />
        </Style>   
    </UserControl.Resources>

    <WrapPanel>
        <Button Command="{Binding ReducePrecision}">
            <Image Source="Resources/DecimalLess.png" />
        </Button>
        <Button Command="{Binding IncreasePrecision}">
            <Image Source="Resources/DecimalMore.png" />
        </Button>
    </WrapPanel>
</UserControl>

Code behind:
namespace DataGridFormatting
{
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    
    public partial class PrecisionAdjuster : UserControl
    {
        public static readonly DependencyProperty PrecisionProperty = DependencyProperty.Register(
            "Precision",
            typeof(int),
            typeof(PrecisionAdjuster),
            new PropertyMetadata(default(int)));

        public int Precision
        {
            get { return (int)GetValue(PrecisionProperty); }
            set { SetValue(PrecisionProperty, value); }
        }

        public PrecisionAdjuster()
        {
            InitializeComponent();

            DataContext = new PrecisionAdjusterViewModel();

            Binding binding = new Binding("Precision") { Mode = BindingMode.TwoWay };
            SetBinding(PrecisionProperty, binding);
        }
    }
}

ViewModel:
namespace DataGridFormatting
{
    using System.ComponentModel;
    using System.Windows.Input;
  
    public class PrecisionAdjusterViewModel : INotifyPropertyChanged
    {
        private int precision;

        public PrecisionAdjusterViewModel()
        {
            Precision = 2;
            ReducePrecision = new RelayCommand(OnReducePrecision);
            IncreasePrecision = new RelayCommand(OnIncreasePrecision);
        }
 
        public int Precision
        {
            get { return precision; }
            set
            {
                precision = value;
                OnPropertyChanged("Precision");
            }
        }

        public ICommand ReducePrecision { get; set; } 

        public ICommand IncreasePrecision { get; set; }

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

        private void OnReducePrecision()
        {
            if (Precision > 0)
            {
                Precision--;
            }
        }

        private void OnIncreasePrecision()
        {
            Precision++;
        }
    }
}

In the code behind, we bind property Precision of the view-model with DependencyProperty Precision of the UserControl. The DependencyProperty Precision can be set outside of this UserControl, for example as the initial precision value. If this is not set, the default value is 2 as defined in the view-model. Everytime we click the button to increase or reduce precision, the precision is adjusted accordingly within the view-model. RelayCommand is a helper class implementing ICommand as described here.

The Main Window

For simplicity, I'm not going to create view-model for the MainWindow. I'll put the test data and the property we're binding to in the code behind:
namespace DataGridFormatting
{
    using System.Collections.ObjectModel;
    using System.Windows;

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            DataGridSource = new ObservableCollection<ItemRate>
            {
                new ItemRate("AAA", 3.0123456789),
                new ItemRate("BBB", 1.8478913937),
                new ItemRate("CCC", 2.3891383276),
                new ItemRate("DDD", 1.2334392431)
            };

            InitializeComponent();
        }

        public ObservableCollection<ItemRate> DataGridSource { get; set; }
    }
}
XAML:
(Note: when you copy and paste the below XAML to Visual Studio, it'll not recognize NumericFormatConverter. But read on, we'll create this in the next section.)
<Window x:Class="DataGridFormatting.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:DataGridFormatting"
        Title="MainWindow" Height="250" Width="200"
        Name="ThisWindow">

    <Window.Resources>
        <local:NumericFormatConverter x:Key="MyNumericFormatConverter" />
    </Window.Resources>

    <StackPanel DataContext="{Binding ElementName=ThisWindow}">
        <StackPanel Orientation="Horizontal" Margin="10">
            <TextBlock Text="Choose format:   "/>
            <ComboBox x:Name="FormatSpecifierInput" Width="40">
                <ComboBoxItem Content="N" IsSelected="True" />
                <ComboBoxItem Content="P" />
                <ComboBoxItem Content="C" />
            </ComboBox>
        </StackPanel>

        <local:PrecisionAdjuster x:Name="MyPrecisionAdjuster" Precision="4" HorizontalAlignment="Center" />

        <DataGrid ItemsSource="{Binding DataGridSource}"
                  AutoGenerateColumns="False" Margin="10" HorizontalAlignment="Center">
            <DataGrid.Columns>
                <DataGridTextColumn Header="Items" Binding="{Binding Item}" />
                <DataGridTemplateColumn Header="Rates">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <TextBlock>
                                <TextBlock.Text>
                                    <MultiBinding Converter="{StaticResource MyNumericFormatConverter}">
                                        <Binding Path="Rate" />
                                        <Binding ElementName="FormatSpecifierInput" Path="Text" />
                                        <Binding ElementName="MyPrecisionAdjuster" Path="Precision" />
                                    </MultiBinding>
                                </TextBlock.Text>
                            </TextBlock>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>
    </StackPanel>
</Window>

First we create a ComboBox containing the format we want to display our rates in. In this example, the possible values are N (Number), P (Percent) and C (Currency). I'm using .NET standard numeric format strings as described here. Name the ComboBox FormatSpecifierInput, so that we can bind this to the DataGrid later on.

Next we put the UserControl PrecisionAdjuster we created earlier into the Window. Name this control MyPrecisionAdjuster, set the initial Precision to 4.

The DataGrid has 2 columns with ItemsSource bound to property DataGridSource of type ObservableCollection<ItemRate>. The first column is DataGridTextColumn bound to property Item of class ItemRate.

    public class ItemRate
    {
        public ItemRate(string item, double rate)
        {
            Item = item;
            Rate = rate;
        }

        public string Item { get; set; }

        public double Rate { get; set; }
    }

The second column is a DataGridTemplateColumn TextBlock with Text property bound to:

  1. Property Rate of ObservableCollection<ItemRate> (bound to property DataGridSource)
  2. Property Text of the ComboBox FormatSpecifierInput
  3. DependencyProperty Precision of the UserControl MyPrecisionAdjuster
Use MultiBinding to describe a collection of Binding objects attached to a single binding target property. The Converter property is a IMultiValueConverter. We define the class that implements IMultiValueConverter in Windows.Resources. Note that at this point in time, we have yet to create this multi value converter class. Let's name this class NumericFormatConverter.


The IMultiValueConverter implementation: NumericFormatConverter

namespace DataGridFormatting
{
    using System;
    using System.Globalization;
    using System.Windows.Data;

    public class NumericFormatConverter : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            double number = System.Convert.ToDouble(values[0]);
            string formatSpecifier = System.Convert.ToString(values[1]);
            int precision = System.Convert.ToInt16(values[2]);
            string format = "{0:" + formatSpecifier + precision + "}";  // eg. {0:P4}, {0:N2} 
            return string.Format(format, number);
        }

        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}

Note that the order of object[] values is important. If we change the MultiBinding order in the XAML to something like this for example:

<MultiBinding Converter="{StaticResource MyNumericFormatConverter}">
    <Binding ElementName="FormatSpecifierInput" Path="Text" />
    <Binding Path="Rate" />
    <Binding ElementName="MyPrecisionAdjuster" Path="Precision" />
</MultiBinding>

Then we'll need to change NumericFormatConverter to:
    string formatSpecifier = System.Convert.ToString(values[0]);
    double number = System.Convert.ToDouble(values[1]);
    int precision = System.Convert.ToInt16(values[2]);

You might want to add some validation in the Convert method to warn your fellow developers to pay attention to the order.

Source Code

https://github.com/velianarie/DataGridFormatting

Wednesday, March 4, 2015

WPF MVVM binding to Windows Forms control

For a WPF application I’m currently working on, I need to use a legacy Windows Form control. This legacy control has a public function which takes in a complex POCO to do its magic. My WPF view-model handles the creation of this POCO and I need to somehow find a way to bind this POCO created by the view-model to the legacy Windows Form control.

Let’s illustrate this with a very simple example.

In my WPF window I want to reuse a Windows Form control that takes in a Person object and knows how to display it using some other Windows Form built-in controls eg. TextBox Name and Age. The display of the Person object will be triggered by a WPF button.

Steps to solve in a nutshell:
1) Wrap the Windows Form control in a WPF control using WindowsFormsHost
2) Add DependencyProperty of type POCO to the WPF control
3) In WPF main window, add the WPF control and bind the DependencyProperty to property of type POCO in the view-model

The Windows Form Control

The Windows Form control has a public function that takes in a Person object and then display it.

namespace WfControlHostedInWpfControl
{
    using System;
    using System.Windows.Forms;

    public partial class WindowsFormControl : UserControl
    {
        public WindowsFormControl()
        {
            InitializeComponent();
        }

        public void WorkYourMagic(Person person)
        {
            TextBoxName.Text = person.Name;
            TextBoxAge.Text = Convert.ToString(person.Age);
        }
    }
}

The POCO

namespace WfControlHostedInWpfControl
{
    public class Person
    {
        public string Name { get; set; }

        public int Age { get; set; }
    }
}

The WPF Control

The WPF control is a wrapper around the Windows Form control.

The XAML is very simple. It only contains a WindowsFormsHost that hosts our WindowsFormControl. Don’t forget to give the host a name so we can refer to it in the code behind later on.

<UserControl x:Class="WfControlHostedInWpfControl.WpfControl"
             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:local="clr-namespace:WfControlHostedInWpfControl"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    
    <WindowsFormsHost Name="MyHost">
        <local:WindowsFormControl />
    </WindowsFormsHost>
    
</UserControl>

In the code behind, we retrieve the original Windows Form Control by calling the Child property of WindowsFormsHost. We also define ComplexPoco dependency property of type Person, so that we can bind this property from our WPF main window later on. When this dependency property changes, the public function in the Windows Form control will be called, taking in the updated Person object.

namespace WfControlHostedInWpfControl
{
    using System.Windows;
    using System.Windows.Controls;

    public partial class WpfControl : UserControl
    {
        public static readonly DependencyProperty ComplexPocoProperty = DependencyProperty.Register(
            "ComplexPoco",
            typeof(Person),
            typeof(WpfControl),
            new FrameworkPropertyMetadata(
                default(Person),
                FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
                OnPropertyChanged));

        public Person ComplexPoco
        {
            get { return (Person)GetValue(ComplexPocoProperty); }
            set { SetValue(ComplexPocoProperty, value); }
        }

        private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            WpfControl thisControl = (WpfControl)d;
            WindowsFormsHost wfHost = thisControl.MyHost;
            WindowsFormControl wf = (WindowsFormControl)wfHost.Child;
            wf.WorkYourMagic((Person)e.NewValue);
        }

        public WpfControl()
        {
            InitializeComponent();
        }
    }
}

The WPF Main Window

<Window x:Class="WfControlHostedInWpfControl.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WfControlHostedInWpfControl"
        Title="MainWindow" Height="200" Width="300">

    <StackPanel>
        <local:WpfControl ComplexPoco="{Binding Person}" />
        <Button Content="Show me the magic!" Command="{Binding ShowMagic}" />
    </StackPanel>
    
</Window>

Here we initialize WpfControl we created earlier and bind the dependency property ComplexPoco to Person property in the view-model. The button is bound to ShowMagic command in the view-model. Every time we click on the button, a random Person object will be displayed in the WPF Control.

Code behind:

namespace WfControlHostedInWpfControl
{
    using System.Windows;

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            DataContext = new ViewModel();
        }
    }
}

The view-model:

namespace WfControlHostedInWpfControl
{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Windows.Input;

    public class ViewModel : INotifyPropertyChanged
    {
        private Person person;
        private readonly List<Person> repository;

        public ViewModel()
        {
            repository = new List<Person>
            {
                new Person { Name = "John", Age = 20 }, 
                new Person { Name = "Amber", Age = 24 },
                new Person { Name = "Sally", Age = 30 }, 
                new Person { Name = "Abe", Age = 50 }
            };

            ShowMagic = new RelayCommand(PickRandomPerson);
        }

        public Person Person
        {
            get { return person; }
            set
            {
                person = value;
                OnPropertyChanged("Person");
            }
        }

        public ICommand ShowMagic { get; set; }

        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        private void PickRandomPerson()
        {
            int index = new Random().Next(0, repository.Count);
            Person = repository[index];
        }
    }
}

RelayCommand is a helper class implementing ICommand as described here.

There you have it! A simplified toy example of the actual problem I was dealing with.

Source Code

https://github.com/velianarie/WfControlHostedInWpfControl