3

I'm about to redo an old WinForms application as a WPF application. The core of this applicaton is a custom "grid" component. I'd like some ideas on the best way to do this as a WPF component.

The application displays a grid of data for different countries/sectors. Each cell of the grid displays different information (e.g. graph, image) depending on the available data for that country/sector.

I have a domain model assembly that I want to keep clean - to maximize reuse. The structure is as follows:

  • Table
    • Continents
    • Countries
    • Sectors
    • Data[country, sector]

The grid displays countries down the left and sectors across the top.

In the current application, the grid component has a (POCO) Table property and an Refresh() methods to manually redraw it. So, if the Table is updated, the parent of the grid component refreshes it. The grid component also has a number of events that are fired if a continent, country or cell is clicked - so that the parent can response with pop-up menus, etc.

This all works fine.

However, I'm wondering whether this is the correct model to use for a WPF application. Looking at many of the WPF example, they support data-binding, etc. But, it's not clear, from the simple examples, how I might bind a complex object to my components - or whether it would even be worthwhile.

Also, the WinForms component is completely custom drawn - there are no sub-controls (e.g. Labels) in use. Would it be better to use a WPF user control and build the table from a GridLayout and lots of Label, Shape, etc controls? In practice, they are maybe 20 rows and 20 columns in the grid, and the user regular removes and adds countries/sectors (rows/columnms) while using the application.

My immediate goal is to make sure my design plays well in the WPF eco-system, but I have a secondary goal of learning how to do things in a WPFy way - given this is my first WPF app. I'm pretty on top of the use of building a general WPF app - it's just the custom control stuff that remains a little fuzzy (even after reading around it a little).

Any insights/guidance would be appreciated.

1
  • an image of existing control would help. Commented Apr 25, 2011 at 11:41

1 Answer 1

1

You definitely want to adapt the MVVM approach, as outlined by Josh Smith. Practically, this means that your custom grid component will be contained in it's own View. Backing the view will be your ViewModel, where you will define an ObservableCollection of objects containing your data. These objects will probably come from your Model. This interaction is shown below:

Models:

public class TableData
{
    public string Country { get; set; }
    public string Continent { get; set; }
    public object Sector { get; set; }
}

public class TableManager : ITableManager
{
    public Collection<TableData> Rows;

    public void GetData()
    {
        this.Rows = new Collection<TableData>();
        this.Rows.Add(...
    }
}

ViewModel:

public class TableViewModel
{
    private ITableManager _tableManager;

    public TableViewModel() : base(new TableManager())
    {
    }

    // for dependency injection (recommended)
    public TableViewModel(ITableManager tableManager)
    {
        _tableManager = tableManager;
        _tableManager.GetData();
    }

    public ObservableCollection<TableData> Rows
    { 
        get { return _tableManager.Rows; }
    }
}

View:

<ctrls:CustomDataGrid
    ItemsSource={Binding Rows}
    AutoGenerateColumns=True
    >
    <!-- Use AutoGenerateColumns if the # of sectors is dynamic -->
    <!-- Otherwise, define columns manually, like so: -->
    <DataGridTextColumn
         Width="*"
         Header="SectorA"
         Binding="{Binding Country}
         />
</ctrls:CustomDataGrid>

I used CustomDataGrid in the view because I assume you're going to subclass your own DataGrid. This will allow you to override events to customize the DataGrid to your liking:

public class CustomDataGrid : DataGrid
{
    public override Event... 
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.