Feeds:
Posts
Comments

Archive for the ‘C#’ Category

After I added a Split Page to a Windows Store app that was created with the Blank App template, I got the error mentioned in the title whenever I opened the xaml file of the split page.

I got rid of it by deleting the .suo file of the Visual Studio solution.

 

Read Full Post »

I’ve captured a video of the BarModel Player for the following word problem:

Ryan had $200 more than Danish at first. Ryan gave ¾ of his money to Danish. Danish in return gave 2/3 of his money to Ryan. In the end, Ryan had $180 more than Danish. Find the amount of money Danish had in the end.

You can see how the bar model is created step by step, and boxes moving from one bar to another bar in action.

Read Full Post »

Customize WPF ComboBox

There is a column in the Lines ListView of the Edit Model dialog box of the GeometryViz3D tool for the user to choose the color of the lines. Previously the colors are shown as plain text in the ComboBoxes. It will be more user friendly if the colors can be illustrated as the actual colors as shown in the following screen shot.

Here is the XAML code I use to achieve this. The key idea is customize the ItemTemplate of the ComboBoxes bound to the Color column of the Lines ListView by drawing a Rectangle.

The ItemSource property of the ComboBox is bound to the Colors property of the EditModelViewModel object, which is an array of strings that are color names, including Black, Cyan, and so on. And therefore, each item of the ComboBox is bound to the name of a color. We bind the color name to the Fill property of the Rectangle by taking advantage of the WPF’s built-in feature that converts a color name to a Brush.

The remaining issue is how to specify the size of the Rectangle. If we don’t specify, the actual height and width will both be 0. After some research using the snoop tool, I decided to determine the Height based on the FontSize of the ComboBox, and the Width based on the ActualWidth the ComboBox. Since the ComboBox is an ancestor of the items of the drop down list, we use the ComboBox as the RelativeSource. To make the Height of the ComboBox similar to the ComboBoxes in other columns, we have to adjust the value a little bit. This is where the DoubleAdditionConverter comes in. We make the Height to be FontSize + 2, and Width to be ActualWidth – 4.

Since the Height and Width of the Rectangle will not change after initialized, we set the binding Mode to OneTime.

The SelectedValue property of the ComboBox is bound to the Color property of the G3DLine object that is bound to the ListViewItem.

<Window.Resources>
  <local:DoubleAdditionConverter x:Key="doubleAdditionConverter" />
  …
  <DataTemplate x:Key="colorCellTemplate">
    <ComboBox ItemsSource="{Binding Colors}"
              SelectedValue="{Binding Color}"
              Margin="-6, 0, -6, 0" >
      <ComboBox.ItemTemplate>
        <DataTemplate>
          <Rectangle Fill="{Binding Mode=OneTime}"
                     Height="{Binding Mode=OneTime,
                       RelativeSource={RelativeSource FindAncestor,
                         AncestorType={x:Type ComboBox}},
                       Path=FontSize,
                       Converter={StaticResource doubleAdditionConverter},
                       ConverterParameter=2}"

                     Width="{Binding Mode=OneTime,
                       RelativeSource={RelativeSource FindAncestor,
                         AncestorType={x:Type ComboBox}},
                       Path=ActualWidth,
                       Converter={StaticResource doubleAdditionConverter},
                       ConverterParameter=-4}" />
        </DataTemplate>
      </ComboBox.ItemTemplate>
    </ComboBox>
  </DataTemplate>
</Window.Resources>

<ListView Margin="3"
          ItemsSource="{Binding Lines}"
          SelectedValue="{Binding SelectedLine}">
  <ListView.View>
    <GridView>
      <GridView.Columns>
        …
        <GridViewColumn Header="Color" Width="120"
                        CellTemplate="{StaticResource colorCellTemplate}" />
      </GridView.Columns>
    </GridView>
  </ListView.View>
</ListView>

Here is the source code of the DoubleAdditionConverter:

public class DoubleAdditionConverter : IValueConverter
{
    #region IValueConverter Members

    public object Convert(object value, Type targetType, object parameter,
        System.Globalization.CultureInfo culture)
    {
        double v = (double)value;
        double p = Double.Parse((string)parameter);
        return v + p;
    }

    public object ConvertBack(object value, Type targetType, object parameter,
        System.Globalization.CultureInfo culture)
    {
        double v = (double)value;
        double p = Double.Parse((string)parameter);
        return v - p;
    }

    #endregion
}

The entire source code can be found at the GeometryViz3D project on CodePlex.

Read Full Post »

CommandManager.InvalidateRequerySuggested()

In a WPF application, I have several Button controls each bound to a ICommand property of a ViewModel. In one of the method of a ViewModel, I invoke a method with a worker thread. When the method is done, it will change the value of a property, which would causes the CanExecute() method of the ICommand objects to return a different value, which would, in turn, cause the Button controls to be enabled or disabled accordingly. But nothing changes. After doing some research, I’ve found that we can call the CommandManager.InvalidateRequerySuggested() method to force the Buttons bound to ICommand object to be refreshed.

private void DoSomething()
{
    ThreadPool.QueueUserWorkItem(state =>
        {
            DoSomethingInBackgroud();
            SynchronizationContext.Current.Post(s =>
                {
                    CommandManager.InvalidateRequerySuggested();
                }, null);
       });
}

The DoSomething() method will be called when the Execute() method of the ICommand object bound to a button is called. The ThreadPool.QueueUserWorkItem() method queues the lambda code block passed in to wait its turn to be run by a worker thread. Once the DoSomethingInBackground() method is done by the worker thread, another lambda code block containing the call to the CommandManager.InvalidateRequerySuggested() method is queued to the UI thread, represented by SynchronizationContext.Current, to make sure that this method will be executed by the UI thread.

Read Full Post »