Best wpf questions in April 2011

WPF Keep the most left column of a treeview visible while scrolling horizontally

19 votes

Hi,

I implemented a treeview with columns in WPF using ControlTemplate and a stackpanel of GridViewRowPresenter. I followed this article : http://blogs.msdn.com/b/atc_avalon_team/archive/2006/03/01/541206.aspx

It works perfectly!

However, I would like to keep the left column (with the names) visible while scrolling horizontally.

It would be like 'freeze panes' on microsoft excel on the first column.

An idea, anyone?

Thanks Frederic

The problem with the GridViewRowPresenter solution is that the tree is inextricable from the other columns. I figure you need it to be separate so that you can put the horizontal-only ScrollViewer around the columns, and I doubt this is easy (if possible) to do to the project in the article you linked.

This project that I slapped together to figure something out is quite rough around the edges. There are a number of issues you would need to work out separately that I didn't fine-tune:

  1. Templates and styling so that lines match up, and other visual tweaks.
  2. Re-introducing the GridView aspects of the linked project for headers and the columns.
  3. A splitter for adjusting the size of the first column (containing the tree).

Like the article project, I used a tree of Type objects as the data source.

The crux of getting this to work was wrapping the data objects in an ExpandingContainer object. The important things about this INPC class is the IsExpanded property (for binding) and the collection of children:

public class ExpandingContainer : INotifyPropertyChanged {
    public object Payload { get; private set; }

    public ObservableCollection<ExpandingContainer> Children { get; private set; }

    public ExpandingContainer( object payload ) { ... }

    private bool _isexpanded;
    public bool IsExpanded {
        get { return _isexpanded; }
        set {
            if ( value == _isexpanded )
                return;
            _isexpanded = value;
            PropertyChanged.Notify( () => IsExpanded );
        }
    }

    public event PropertyChangedEventHandler PropertyChanged = (o,e) => {};
}

As for the XAML, first let's get some resources out of the way:

<!-- bind ExpandingContainer.IsExpanded to TreeViewItem.IsExpanded -->
<Style TargetType="TreeViewItem">
    <Setter Property="IsExpanded"
            Value="{Binding IsExpanded, Mode=TwoWay}" />
</Style>

<!-- for binding ExpandingContainer.IsExpanded to visibility later -->
<BooleanToVisibilityConverter x:Key="boolvis" />

<!-- the TreeViewItems should display the Type's name -->
<HierarchicalDataTemplate DataType="{x:Type loc:ExpandingContainer}"
                          x:Key="treeViewSide"
                          ItemsSource="{Binding Children}">
    <TextBlock Text="{Binding Payload.Name}" />
</HierarchicalDataTemplate>

<!-- the column side are naively simple, the ItemsControl of children has its
     visibility bound to ExpandingContainer, but the "columns" are just
     StackPanels of TextBlocks -->
<HierarchicalDataTemplate DataType="{x:Type loc:ExpandingContainer}"
                          x:Key="columnSide">
    <StackPanel>
        <StackPanel.Resources>
            <Style TargetType="TextBlock">
                <Setter Property="Margin" Value="10,0" />
            </Style>
        </StackPanel.Resources>
        <StackPanel Orientation="Horizontal">
            <TextBlock Text="{Binding Payload.IsAbstract}" />
            <TextBlock Text="{Binding Payload.Namespace}" />
            <TextBlock Text="{Binding Payload.GUID}" />
        </StackPanel>
        <ItemsControl ItemsSource="{Binding Children}"
                      Visibility="{Binding IsExpanded, Converter={StaticResource boolvis}}" />
    </StackPanel>
</HierarchicalDataTemplate>

<!-- a style can't refer to itself, so this was just to apply it to all ItemsControls -->
<Style TargetType="ItemsControl">
    <Setter Property="ItemTemplate"
            Value="{StaticResource columnSide}" />
</Style>

I originally tried nesting the horizontal-only ScrollViewer containing the right columns inside the vertical-only ScrollViewer that was responsible for the TreeView, but that produced the strange requirement that you had to scroll to the bottom to scroll horizontally. So I separated them further, placing the ScrollViewers side-by-side.

To keep the vertical scrollbar on the far right, I hid both scrollbars around the TreeView and use only the scrollbars around the columns. Syncing the vertical scrolling is done in code-behind, but for a more MVVM way to do it, you could make an attached behavior to facilitate binding them to each other.

<DockPanel>
    <ScrollViewer VerticalScrollBarVisibility="Hidden"
                  HorizontalScrollBarVisibility="Hidden"
                  DockPanel.Dock="Left"
                  Name="treescroller">
        <TreeView ItemsSource="{Binding Items}"
                  ItemTemplate="{StaticResource treeViewSide}"
                  Padding="0,0,0,20">
        </TreeView>
    </ScrollViewer>
    <ScrollViewer Name="columnscroller"
                  HorizontalScrollBarVisibility="Auto"
                  VerticalScrollBarVisibility="Auto"
                  ScrollChanged="columnscroller_ScrollChanged">
        <ItemsControl ItemsSource="{Binding Items}" />
    </ScrollViewer>
</DockPanel>

And lastly, the important bit of the code-behind (minus making the data objects and setting the DataContext property):

private void columnscroller_ScrollChanged( object sender, ScrollChangedEventArgs e ) {
    treescroller.ScrollToVerticalOffset( columnscroller.VerticalOffset );
}

Hope it helps, or at least provides a different perspective.

If I really needed a good one that filled every need I could think of for a hybrid TreeView+ListView, I'd probably look at professional controls first before spending the necessary time to polish a home-grown solution. This kind of thing is better when the requirements for such display are simple.

WPF without XAML

14 votes

Architecturally, I think WPF is pretty amazing. In general, I'm a big fan of the underlying rendering/animation inner workings. The flexibility of the templating and styling set up is pretty impressive.

But I loathe XAML - I feel like it complicates many things. I've used it on large and small applications and I've found myself many times trying to figure out how to do something in XAML for which the underlying principle is basic but the syntax is quirky. Not only that, but I've wondered many times how heavy certain parts of the parsing/binding are. (I know it's compiled, but I'm not sure how much is still evaluated at runtime)

XAML is just one way of building and loading the visual tree. Are there any frameworks for simplifying building the visual tree in a non-XML, code-based (but still largely declarative) way? Specifically, I'm interested in frameworks that mitigate any of the following issues while retaining an MVVM approach:

  1. Strongly typed binding. Specify that the ViewModel must conform to a specific type. I assume BaseBinding uses reflection under the hood and I'm a bit skeptical as to the speed of that, not to mention broken bindings being annoying.

  2. Faster binding, non-INotifyPropertyChanged binding. It seems like some sort of BindableProperty<T> could be created and the binding could listen directly to that rather than receiving all ViewModel property changes. And the use of a direct callback versus a string argument would also seem to be advantageous.

  3. A different approach to resource management; again, strongly typed dictionaries of some sort could be pretty nice. I'd almost like to see styles as lambdas or something to capture the strongly typed aspect.

In summary, any frameworks that are non-XAML based, fit well with MVVM, and are strongly typed?

Desclaimer - i LOVE xaml. I think it's the best thing to happen to UI technology since..well..i wanted to say "winforms" but that really sucked - so since the dawn of history!

Let me break down your requirements from this new and improved framework:

  1. Strongly typed bindings - While i agree it might be useful in SOME settings to specific the binding in a strongly typed way, i frequently find myself using the fact that binding is completely loose to be very useful. the runtime discovery of properties is an incredibly powerful property of Xaml and the binding mechanism. In my experience you learn pretty quickly to find and fix binding issues, and the runtime errors are very detailed. It may not be ideal - but it's pretty good.
  2. Faster binding - performance, is fairly fast for most situations. You can always provide an ICustomTypeDescriptor to improve performance in extreme cases. As for that Bindable property with a callback - how about some kind of Dependency Property? (i do concede that the syntax is somewhat lacking). However, for most uses i found the INotifyPropertyChanged interface to be sufficient. The binding mechanism only cares about the fact that there was a change, and it works very well in it's current form. Why do you care how the framework solves this problem - as long as it works well?
  3. Resource Dictionaries - This is another implementation issue that mostly influences the framework and it's internal working. Why do you care how they are implemented? They work pretty well.

I suspect you might be overusing codebehind to solve problems that can and should be solved in Xaml. Which exposes you to the framework's way of solving these different issues, and which I have almost never had to deal with in WPF. The clear seperation provided by Xaml between "things that are the GUI" and "Things that are your code" makes it harder for you to interfere with the UI by using the Code. But WPF provides MANY different mechanism to solve these solutions in an elegant way by using Xaml.

If you don't like coding it (personally i don't like messing with UI - it never ends) - Hire a Xaml Expert. They usually have better taste in UI then developers anyway. And if you can't - Learn it! it's a great tool if you take the time to understand it. No framework will solve the problem of groking it's use.

Pragmatic use of code-behind in MVVM pattern

10 votes

I'm trying to follow the MVVM pattern in a WPF application as good as I can, mainly to be able to create unit tests for my ViewModel logic.

In most cases data binding between ViewModel properties and properties of visual elements works fine and is easy. But sometimes I encounter situations where I cannot see an obvious and straightforward way while a solution to access and manipulate controls from code-behind is very easy.

Here is an example of what I mean: Inserting a text fragment into a TextBox at the current caret position

Since CaretIndex isn't a dependency property it can't be bound directly to a ViewModel's property. Here is a solution to work around this limitation by creating a dependency property. And here is the solution to do this in code-behind. I would prefer the code-behind way in this situation. Another problem I recently had was binding a dynamic collection of columns to a WPF datagrid. It was clear and simple to program in code-behind. But for a MVVM-friendly databinding approach I could only find work arounds in several blogs which all looked quite complex to me and had various limitations in one or the other aspect.

I don't want to keep the MVVM architecture clean of code-behind logic at all costs. If the amount of work arounds is too big, a MVVM-friendly solution requires a lot of code which I don't fully understand (I'm still a WPF beginner) and is too time consuming I prefer a code-behind solution and sacrifice automatic testability of a few parts of my application.

For the mentioned pragmatic reasons I am looking now for "patterns" to make controlled use of code-behind in an application without breaking the MVVM architecture or without breaking it too much.

Up to now I've found and tested two solutions. I will draw rough sketches with the Caret Position example:

Solution 1) Give the ViewModel a reference to the View through an abstract interface

  • I would have an interface with methods which would be implemented by the view:

    public interface IView
    {
        void InsertTextAtCaretPosition(string text);
    }
    
    public partial class View : UserControl, IView
    {
        public View()
        {
            InitializeComponent();
        }
    
        // Interface implementation
        public void InsertTextAtCaretPosition(string text)
        {
            MyTextBox.Text = MyTextBox.Text.Insert(MyTextBox.CaretIndex, text);
        }
    }
    
  • Inject this interface into the ViewModel

    public class ViewModel : ViewModelBase
    {
        private readonly IView _view;
    
        public ViewModel(IView view)
        {
            _view = view;
        }
    }
    
  • Execute code-behind from a ViewModel's command handler through the interface methods

    public ICommand InsertCommand { get; private set; }
    // Bound for instance to a button command
    
    // Command handler
    private void InsertText(string text)
    {
        _view.InsertTextAtCaretPosition(text);
    }
    

To create a View-ViewModel pair I would use dependency injection to instantiate the concrete View and inject it into the ViewModel.

Solution 2) Execute code-behind methods through events

  • The ViewModel is publisher of special events and command handlers raise those events

    public class ViewModel : ViewModelBase
    {
        public ViewModel()
        {
        }
    
        public event InsertTextEventHandler InsertTextEvent;
    
        // Command handler
        private void InsertText(string text)
        {
            InsertTextEventHandler handler = InsertTextEvent;
            if (handler != null)
                handler(this, new InsertTextEventArgs(text));
        }
    }
    
  • The View subscribes to these events

    public partial class View : UserControl
    {
        public View()
        {
            InitializeComponent();
        }
    
        private void UserControl_Loaded(object sender, RoutedEventArgs e)
        {
            ViewModel viewModel = DataContext as ViewModel;
            if (viewModel != null)
                viewModel.InsertTextEvent += OnInsertTextEvent;
        }
    
        private void UserControl_Unloaded(object sender, RoutedEventArgs e)
        {
            ViewModel viewModel = DataContext as ViewModel;
            if (viewModel != null)
                viewModel.InsertTextEvent -= OnInsertTextEvent;
        }
    
        private void OnInsertTextEvent(object sender, InsertTextEventArgs e)
        {
            MyTextBox.Text = MyTextBox.Text.Insert(MyTextBox.CaretIndex, e.Text);
        }
    }
    

I am not sure if the Loaded and Unloaded events of the UserControl are good places to subscribe and unsubscribe to the events but I couldn't find problems during test.

I have tested both approaches in two simple examples and they both seem to work. Now my questions are:

  1. Which approach do you think is preferable? Are there any benefits or downsides of one of the solutions which I possibly don't see?

  2. Do you see (and perhaps practice) other solutions?

Thank you for feedback in advance!

Developing WPF applications I found both ways useful. If you need just one call from ViewModel to View, the second option, with event handler, looks simpler and good enough. But if you are requiring more complex interface between these layers, then it makes sense to introduce interface.

And my personal preference is to revert your option one and have a IViewAware interface implemented by my ViewModel and inject this ViewModel into View. Looks like an option three.

public interface IViewAware
{
    void ViewActivated();
    void ViewDeactivated();

    event Action CloseView;
}

public class TaskViewModel : ViewModelBase, IViewAware
{

    private void FireCloseRequest()
    {
        var handler = CloseView;
        if (handler != null)
            handler();
    }

    #region Implementation of IViewAware        
    public void ViewActivated()
    {
        // Do something 
    }

    public void ViewDeactivated()
    {
        // Do something 
    }

    public event Action CloseView;    
    #endregion
}

And this a simplified code for your View:

    public View(IViewAware viewModel) : this()
    {
        _viewModel = viewModel;

        DataContext = viewModel;
        Loaded += ViewLoaded;

    }

    void ViewLoaded(object sender, RoutedEventArgs e)
    {
        Activated += (o, v) => _viewModel.ViewActivated();
        Deactivated += (o, v) => _viewModel.ViewDeactivated();

        _viewModel.CloseView += Close;
    }

In real application I usually use an external logic to connect V and VM, for example Attached Behaviors.

C# WPF Update a progressbar from another thread

10 votes

Hi, I'm stuck trying to update a progressbar from other threads ran in a different class. To explain what I do I think a picture will be better. I want to update the progressbar in the //HERE point :enter image description here

I've tried using a delegate, tried with ReportProgress and I think i've basically tried to use everything google reported in the first 100 results, without success. I'm still learning WPF and this might be silly way to proceed, i'm looking for a quick and dirty way to get the work done but feel free to tell me what I should redesign for a cleaner application.

EDIT : More code.

In ExecutorWindow.xaml.cs :

public void RunExecutor()
{
    // CREATE BACKGROUNDWORKER FOR EXECUTOR
    execBackground.DoWork += new DoWorkEventHandler(execBackground_DoWork);
    execBackground.RunWorkerCompleted += new RunWorkerCompletedEventHandler(execBackground_RunWorkerCompleted);
    execBackground.ProgressChanged += new ProgressChangedEventHandler(execBackground_ProgressChanged);
    execBackground.WorkerReportsProgress = true;
    execBackground.WorkerSupportsCancellation = true;
    // RUN BACKGROUNDWORKER
    execBackground.RunWorkerAsync();
}
private void execBackground_DoWork(object sender, DoWorkEventArgs e)
{
    myExecutor = new Executor(arg1, arg2);
    myExecutor.Run();            
}

private void execBackground_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    MessageBox.Show("RunWorkerCompleted execBackground");
}

private void execBackground_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    ExecutorProgressBar.Value += 1;
}

// TESTING 
private void updateProgressBar(int i)
{
    ExecutorProgressBar.Value += i;
}

public delegate void callback_updateProgressBar(int i);

In Executor.cs :

public void Run()
{
    string[] options = new string[2];
    int i = 0;

    while (LeftToRun > 0)
    {
        if (CurrentRunningThreads < MaxThreadsRunning)
        {
            BackgroundWorker myThread = new BackgroundWorker();
            myThread.DoWork += new DoWorkEventHandler(backgroundWorkerRemoteProcess_DoWork);
            myThread.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorkerRemoteProcess_RunWorkerCompleted);
            myThread.ProgressChanged += new ProgressChangedEventHandler(backgroundWorkerRemoteProcess_ProgressChanged);
            myThread.WorkerReportsProgress = true;
            myThread.WorkerSupportsCancellation = true;

            myThread.RunWorkerAsync(new string[2] {opt1, opt2});

            // HERE ?
            CurrentRunningThreads++;
            i++;
            LeftToRun--;

        }
    }

    while (CurrentRunningThreads > 0) { }
    logfile.Close();
    MessageBox.Show("All Tasks finished");
}

private void backgroundWorkerRemoteProcess_DoWork(object sender, DoWorkEventArgs e)
{
    BackgroundWorker myBackgroundWorker = sender as BackgroundWorker;
    string[] options = (string[])e.Argument;
    string machine = options[0];
    string script = options[1];
    // UPDATE HERE PROGRESSBAR ?
    RemoteProcess myRemoteProcess = new RemoteProcess(machine, script);
    string output = myRemoteProcess.TrueExec();
    // UPDATE HERE PROGRESSBAR ?
    this.logfile.WriteLine(output);
}

private void backgroundWorkerRemoteProcess_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    CurrentRunningThreads--;
}

private void backgroundWorkerRemoteProcess_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    //myExecWindow.ExecutorProgressBar.Value = e.ProgressPercentage; // TESTING
    //ExecutorWindow.callback_updateProgressBar(1); // TESTING 
}

EDIT 2 : I got it! Simple in fact, but i guess I've been looking too close to find out.

In my ExecutorWindow class :

private void execBackground_DoWork(object sender, DoWorkEventArgs e)
{
    myExecutor = new Executor(arg1, arg2);
    myExecutor.Run(sender);
}

private void execBackground_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    ExecutorProgressBar.Value += 1;
}

And in my Executor class :

private BackgroundWorker myExecutorWindow;

[...]

public void Run(object sender)
{
            myExecutorWindow = sender as BackgroundWorker;
            string[] options = new string[2];
            int i = 0;

            while (LeftToRun > 0)
            {
                if (CurrentRunningThreads < MaxThreadsRunning)
                {
                    BackgroundWorker myThread = new BackgroundWorker();
                    myThread.DoWork += new DoWorkEventHandler(backgroundWorkerRemoteProcess_DoWork);
                    myThread.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorkerRemoteProcess_RunWorkerCompleted);
                    myThread.ProgressChanged += new ProgressChangedEventHandler(backgroundWorkerRemoteProcess_ProgressChanged);
                    myThread.WorkerReportsProgress = true;
                    myThread.WorkerSupportsCancellation = true;

                    myThread.RunWorkerAsync(new string[2] {opt1, opt2});

                    CurrentRunningThreads++;
                    i++;
                    LeftToRun--;      
                }
            }

[...]

private void backgroundWorkerRemoteProcess_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker myBackgroundWorker = sender as BackgroundWorker;
            myBackgroundWorker.ReportProgress(1);
            // PROCESSING MY STUFF HERE
            myBackgroundWorker.ReportProgress(1);
        }

        private void backgroundWorkerRemoteProcess_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            myExecutorWindow.ReportProgress(1);
        }

Thank you !

I got it! Simple in fact, but i guess I've been looking too close to find out.

In my ExecutorWindow class :

private void execBackground_DoWork(object sender, DoWorkEventArgs e)
{
    myExecutor = new Executor(arg1, arg2);
    myExecutor.Run(sender);
}

private void execBackground_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    ExecutorProgressBar.Value += 1;
}

And in my Executor class :

private BackgroundWorker myExecutorWindow;

[...]

public void Run(object sender)
{
            myExecutorWindow = sender as BackgroundWorker;
            string[] options = new string[2];
            int i = 0;

            while (LeftToRun > 0)
            {
                if (CurrentRunningThreads < MaxThreadsRunning)
                {
                    BackgroundWorker myThread = new BackgroundWorker();
                    myThread.DoWork += new DoWorkEventHandler(backgroundWorkerRemoteProcess_DoWork);
                    myThread.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorkerRemoteProcess_RunWorkerCompleted);
                    myThread.ProgressChanged += new ProgressChangedEventHandler(backgroundWorkerRemoteProcess_ProgressChanged);
                    myThread.WorkerReportsProgress = true;
                    myThread.WorkerSupportsCancellation = true;

                    myThread.RunWorkerAsync(new string[2] {opt1, opt2});

                    CurrentRunningThreads++;
                    i++;
                    LeftToRun--;      
                }
            }

[...]

private void backgroundWorkerRemoteProcess_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker myBackgroundWorker = sender as BackgroundWorker;
            myBackgroundWorker.ReportProgress(1);
            // PROCESSING MY STUFF HERE
            myBackgroundWorker.ReportProgress(1);
        }

        private void backgroundWorkerRemoteProcess_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            myExecutorWindow.ReportProgress(1);
        }

WPF4: Is this indictment of DevExpress WPF controls valid and what is a good alternative vendor?

9 votes

My company is starting a major greenfield development project using DevExpress WPF controls. I just read this critical review of their WPF controls:

"... DevExpress developers completely misunderstood WPF when they developed their WPF controls. I really cannot impress upon you sufficiently well just how much of a displeasure it is using their controls. I feel absolutely terrible (almost guilty) about talking about a vendor with such negativity, but they have made a serious mistake in their WPF suite, it has been a singular source of the most abject frustration for me in about a decade of developing software."

Do you agree that DevExpress does not understand the WPF paradigm and will cause our developers grief during development and maintenance? Can you suggest an alternate vendor of WPF controls? I'm looking for a vendor with WPF controls that will enhance our application while fitting well with the WPF API, binding and MVVM.

Abject frustration is EXACTLY what I experienced thanks to DevExpress. I lost hours of my life attempting to simply bind a combo box. The drop-down list at best would only display my ItemsSource class name multiple times. I even posted a StackOverflow question to figure out what I could possibly be doing wrong. Finally on a whim I tried removing this one line of xaml:

devx:ThemeManager.ThemeName="DeepBlue"

Suddenly my problem went away. It was caused by the Developer Express wpf theme DeepBlue. Discovering the problem was a tremendous relief. My company will now be using Telerik WPF controls. My colleagues are quite happy with DevExpress Asp.Net controls. It is only the WPF suite we are avoiding.

VISIBLOX, WPF: Getting chart points to scroll horizontally?

7 votes

Hi Guys,

I'm using the Visiblox WPF API and am having trouble getting the chart points in my line chart to scroll horizontally. Instead of scrolling, the points are get squashed together, in which, this isn't particularly a problem, except that I expect to have 100s of data points on the chart. I have looked throughout the examples available on the Visiblox website, but couldn't find what I was looking for. Ive attached an example screenshot.

Any ideas?

Thanks for your help, Sparky

Example

By default Visiblox Charts will re-calculate the range to include all the data in the series, so there are two possible approaches: 1) when you add the last point, remove the first one which will effectively move the visible window one point over or 2) set an explicit axis range and update that when you want to move the visible window.

Check out the Visiblox blog for more details on how ranges work at: http://www.visiblox.com/blog/2011/03/visiblox-charts-ranges-demystified

WPF: Where does MVVM stop and code-behind begins?

7 votes

I have created a Window which has a ListView to display a collection of persons. There are also 3 TextBoxes that are supposed to display person's first and last name, and an age. Finally, there's a Button to save the new person data entered in those TextBoxes.

Loading persons into the ListView is done by implementing MVVM. Works like a charm! Also, adding new people to the collection by clicking the Button is also done through MVVM.

But there are two use cases that I am not sure whether it is wiser to use commands, i.e. MVVM, or just plain code-behind. The use cases are:

  1. When user selects a person from the ListView, the TextBoxes should show the person details.
  2. When user types types characters instead of digits in the TextBox that displays person's age, she or he should be warned that the entered data is incorrect.

The reason why I am in doubt whether I should use MVVM or code-behind is because both use cases are related to view only (GUI), i.e. there is no interactivity with the model or application business logic. The ListView item source is bound to a collection of persons ObservableColleciton<Person> and all data related to the selected person is already passed to the view when the ListView is populated with items. In the second use case, again, there is no need to go to ViewModel in order to let it fire the message box about the wrong user input. How about creating a validation callback in the age dependency property of the ViewModel class instead?

Thanks for all clarifications.

The main motivation behind MVVM is separation of concerns, i.e. separate logic from the presentation. What you are describing (search and validation) looks more "logic" to me, so I would put it in the ViewModel (assuming it cannot be performed with databinding of course).

  • Keep in mind that the view is difficult to test, so if there's a chance that the logic you are implementing has significant errors that would be a reason to put it in the viewModel.

  • An alternative (semi-serious but usually effective) method to decide if something belongs to the model or to the viewModel is asking yourself what would happen if you give the view (the Window, UserControl or whatever) to your graphic designer (even if you don't have one, pretend you do). If you are ok with the idea that he could put his c#-incompetent[*] hands on the code behind (and make a mess out of it) it's generally a sign that the code is strictly presentation-related and can safely live in the view. Most times you'll end up moving it to the ViewModel.

[*] just saying for educational purposes, many designers are more c# competent than me :-)

WPF String Format Question

7 votes

I have an input of a random string of twelve characters like this:

ABABABABABAB

I want them to display like this:

ABAB-ABAB-ABAB

How do I format a string in this way. I'm trying to use StringFormat, but it seems like the wrong approach.

            <TextBlock>
                <TextBlock.Text>
                    <Binding Path="Key" Mode="OneWay" StringFormat="???" />
                </TextBlock.Text>
            </TextBlock>

I don't think there is a direct format string that you could use to achieve the formatting you are looking for but you can implement your own IValueConverter and use it to format your string. Here's an example (it's for WP7 but the concept it the same).

How to reference icons inside .resx files from xaml?

7 votes

I am working on a C# WPF application, using .resx files for resource management. Now, I'm trying to add icons (.ico) to the project but I'm running into some problems.

<Image Name="imgMin" Grid.Column="0"
       Stretch="UniformToFill"
       Cursor="Hand" 
       MouseDown="imgMin_MouseDown">
    <Image.Style>
        <Style TargetType="{x:Type Image}">
            <Setter Property="Source" Value="\Images\minimize_glow.ico"/>
            <Style.Triggers>
                <Trigger Property="IsMouseOver" Value="True">
                    <Setter Property="Source" Value="\Images\minimize_glow.ico"/>
                </Trigger>
            </Style.Triggers>
        </Style>
    </Image.Style>
</Image>

This works fine, but when I move the icon into AppResources.resx I run into problems with referencing it in the xaml code. What should I be using instead of the Setter Property=... lines above? This:

<Setter Property="Source" Value="{x:Static res:AppResources.minimize}"/>

doesn't work, I think I probably need to use a different Property than "Source" because Value isn't a string pointing to the icon but the icon itself now. I can't figure out which one to use though - some help, please?

The Source property does not "want" a string, it just converts it when it gets one. If you add an icon to the resources it will be of the type System.Drawing.Icon. You will need to convert it to an ImageSource via converter.

You can do a static access to resources but it needs to comply with the expected syntax of x:Static.

e.g.

xmlns:prop="clr-namespace:Test.Properties"
<Image MaxHeight="100" MaxWidth="100">
    <Image.Source>
        <Binding Source="{x:Static prop:Resources.icon}">
            <Binding.Converter>
                <vc:IconToImageSourceConverter/>
            </Binding.Converter>
        </Binding>
    </Image.Source>
</Image>
public class IconToImageSourceConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        var icon = value as System.Drawing.Icon;
        var bitmap = icon.ToBitmap();

        //http://stackoverflow.com/questions/94456/load-a-wpf-bitmapimage-from-a-system-drawing-bitmap/1069509#1069509
        MemoryStream ms = new MemoryStream();
        bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
        ms.Position = 0;
        BitmapImage bi = new BitmapImage();
        bi.BeginInit();
        bi.StreamSource = ms;
        bi.EndInit();

        return bi;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotSupportedException();
    }
}

Notes:

  • The resource access modifier must be public
  • If the image is added as "Image" you end up with a Bitmap instead of an Icon, which requires a different converter

Has anyone released a more robust BitArray for .NET?

7 votes

After struggling to make the .NET BitArray class work for my needs, I decided to look for a more robust open-source or commerical one on the web. To my surprise, I can't find a single one. I see various suggestions for extension methods or ways to work around limits to BitArray functionality, but nothing resembling a BitArray replacement.

Are we all reinventing the wheel by extending or replacing BitArray?

Ideally, a replacement would have some/all of these features:

  1. Implements IList<bool> rather than just ICollection.

  2. Can cast to various other types such as int (for up to 32-bit BitArrays), bool (for one-bit BitArrays), double, etc.

  3. Implements a ToArray type of method that yields a byte array. It may be parameterized for endianness. Since BitArray can be constructed from a byte array parameter in the constructor, it seems like good closure to be able to return it to a byte array.

  4. Ability to extract sub-BitArrays from it. For example, from an array like 111101, you could extract bits 1 to 4, yielding a new BitArray of 1110.

  5. Bit shifting operators.

  6. Handles indefinite lengths of bits (like BitArray does), but can still cast to limited types like int, just like you can cast a long to an int if you know it will fit.

  7. ?__ I bet there are plenty of other items on people's wish lists.

Do you know of any open-source or commercial implementations out there? If it's open source, it would be nice to have a nonreciprocal license such as Apache, MIT, or Ms-Pl.

Perhaps you are looking for BigInteger in the System.Numerics namespace? It certainly looks like it can do whatever you are asking for.

Is XBAP (WPF via webpage) dead?

7 votes

I see a lot of XBAP related questions posted here without answer. I know that Silverlight and WPF (desktop) applications exists, but don't remember seen one XBAP product. Can anyone tell if XBAP is dead (no applications being developed/supported)? It would be nice if any XBAP developers could give their opinion.

Xbap is ideal for developing line of business apps for large companies. I used to work in that environment, and ensuring everyone had the correct version of an app was a nightmare.

Unfortunately xbap is late to the party. Most companies have solved this problem with existing technologies (SMS Installers, click once etc), also these companies aren't IT based and don't change/upgrade technologies unless they have to (the IT department I used to work in still use VS2003 and have no plans to upgrade).

So, given the glacial pace these departments adopt "new" technologies, and given their reluctance to change development practises, it could be another 5 or 10 years before they write and deploy an xbap application.

So rather than being dead, I think xbap has a limited audience of late adopters.

Binding converted Enum to a ComboBox

6 votes

I tried to bind the following Enum to a ComboBox

Public Enum PossibleActions
  ActionRead
  ActionWrite
  ActionVerify
End Enum

I can't change the Enum itself, but I do not want to display these strings. My intention is just to cut the prefix 'Action' and display 'Read', 'Write' and 'Verify' in the ComboBox. Therefore I wrote a ValueConverter

Public Class PossibleActionsConverter
  Implements IValueConverter

      Public Function Convert(ByVal value As Object, ByVal targetType As System.Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.Convert
        Dim actions() As PossibleActions
        Dim strings() As String

        actions = CType(value, PossibleActions())
        ReDim strings(actions.GetUpperBound(0))
        For i = 0 To actions.GetUpperBound(0)
          strings(i) = actions(i).ToString.Substring(6)
        Next
        Return strings
      End Function

      Public Function ConvertBack(ByVal value As Object, ByVal targetType As System.Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.ConvertBack
        Dim s As String

        s = CStr(value)

        Return [Enum].Parse(GetType(PossibleActions), "Action" & s)
      End Function
    End Class

My XAML looks like

xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:local="clr-namespace:StepEditor"

[...]

<Window.Resources>
    <ObjectDataProvider x:Key="possibleActionsEnum" MethodName="GetValues"
                        ObjectType="{x:Type sys:Enum}">
        <ObjectDataProvider.MethodParameters>
            <x:TypeExtension Type="local:PossibleActions"></x:TypeExtension>
        </ObjectDataProvider.MethodParameters>
    </ObjectDataProvider>
    <local:PossibleActionsConverter x:Key="possibleActionsConverter"></local:PossibleActionsConverter>
</Window.Resources>

[...]
Either:

<ComboBox ItemsSource="{Binding Source={StaticResource possibleActionsEnum}, Converter={StaticResource possibleActionsConverter}}"
          SelectedItem="{Binding SelectedAction}"></ComboBox>

Or:

<ComboBox ItemsSource="{Binding Source={StaticResource possibleActionsEnum}, Converter={StaticResource possibleActionsConverter}}"
          SelectedItem="{Binding SelectedAction, Converter={StaticResource possibleActionsConverter}}"></ComboBox>

My problem is the binding of the selected item. It fails, but I can't figure out why.

The binding of SelectedItem is wrong, because you convert your Enum into Strings, but SelectedItems is a single string. If you want to stick on this architecture, write a converter that converts a single string back to your enum. The Convert and ConvertBack-methods of your existing converter are close to the solution. They can look like:

  Public Function Convert(ByVal value As Object, ByVal targetType As System.Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.Convert
    Dim action As PossibleActions

    action = CType(value, PossibleActions)
    Return action.ToString.Substring(6)
  End Function

  Public Function ConvertBack(ByVal value As Object, ByVal targetType As System.Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.ConvertBack
    Dim s As String

    s = CStr(value)
    Return [Enum].Parse(GetType(PossibleActions), "Action" & s)
  End Function

WPF Temporary Display Freeze

6 votes

I have a standalone WPF application running on .NET 3.5. Every so often, the display simply freezes up for several seconds. This is most noticeable on screens where something is being updated often. Here is a video showing the problem.

While the display is frozen, the interface remains responsive (video).

I've come across some other posts with similar problems who attributed it to a SW/HW rendering issue. To be safe, I disabled HW rendering altogether, but still have the problem.

I ran a file monitor during the freezes to see if there is some extraordinary file access or activity going on, but nothing is out of the ordinary.

Final note: The target platform is a small touch-screen panel PC without much memory or horsepower (512 MB). I only see this issue on the target, never on my development PC, which has much more in the way of resources.

UPDATE

I thought I had fixed the issue by removing some animation code, but it did not work. I am still encountering the problem and I'm at the end of my rope.

Here's some more things I've tried:

  • Upgraded to .NET 4.0. Same behavior.
  • Added debug code to all methods that may be invoked via DispatcherTimer (which are called on the UI thread) to make sure none of them are holding up the UI.

I'm really stumped here and have added a bounty. As I mentioned, the problem only occurs on the target PC (link).

The culprit was the following method call:

new HwndSource(new HwndSourceParameters());

This was added to my application because it patched a memory leak problem in .NET 3.5. This work-around can be found here. If I remove this call, the rendering issues go away.

I took out the call and fixed the memory leak in another way (removing storyboard animation and using code behind instead)

c# Uri loading non deterministic?

6 votes

I am trying to load some BitmapImages from files held on the file system. I have a dictionary of keys and relative filepaths. Unfortunately the Uri constructor seems non deterministic in the way that it will load the images.

Here is my code:

foreach(KeyValuePair<string, string> imageLocation in _imageLocations)
{
    try
    {
        BitmapImage img = new BitmapImage();
        img.BeginInit();
        img.UriSource = new Uri(@imageLocation.Value, UriKind.Relative);

        img.EndInit();
        _images.Add(imageLocation.Key, img);
    }
    catch (Exception ex)
    {
        logger.Error("Error attempting to load image", ex);

    }
}

Unfortunately sometimes the Uris get loaded as relative file Uris and sometimes they get loaded as relative Pack Uris. There doesn't seem to be any rhyme or reason as to which will get loaded which way. Sometimes I get all the Uris loading one way, or just a couple, or most of them, and it will change each time I run the code.

Any ideas what is going on here?

Well, sort of... MSDN has this to say about the UriKind:

Absolute URIs are characterized by a complete reference to the resource (example: http://www.contoso.com/index.html), while a relative Uri depends on a previously defined base URI (example: /index.html)

If you jump into reflector and look around you can see that there are lots of paths for the code to take to resolve what the relative URI should be. Anyhow, it isn't that its non-deterministic, it's more that it is just a major source of frustration for many developers. One thing that you can do is emply the 'BaseUriHelper' class to get to the bottom of how your uris are being resolved.

On the other hand, if you know where your resources are being stored (and you should) I would suggest that you just spare yourself the headache and use an absolute URI to resolve your resources. Works every time, and no goofy code behind the scenes to trip you up when you least expect it.