2

I have a simple (I think) app that reads an SQL database into variables in my program, and I then need to update a gridview defined in XAML with the data I read. I'm constrained to code for .NET 3.5. All the searching I've done on the books I have on XAML, MS .NET help and elsewhere on the Web shows countless examples of doing this from ASP.NET, but none from a C#-XAML combination. I've found doing simple things in XAML ++much++ more difficult and involved than doing the same thing in Winforms, and I'm just not getting this. In particular, data binding seems to me to be a black art. Can someone please look at my XAML and tell me what I need to do or change to populate this control from my C# code-behind?

Here is my XAML:

<Window x:Class="UCCResourceManager.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="UCC Resource Mangler" Height="350" Width="700">
  <Grid>
    <Grid.RowDefinitions>
      <RowDefinition Height="250"/>
      <RowDefinition />
    </Grid.RowDefinitions>

    <ListView Name="grdResource"
              ItemsSource="{Binding}"
              Grid.Row="0">

      <ListView.View>

        <GridView AllowsColumnReorder="false"
              ColumnHeaderToolTip="UCC Resource Table">

          <GridViewColumn DisplayMemberBinding="{Binding Path=ID}"
                          Header="ID"
                          Width="50"/>

          <GridViewColumn DisplayMemberBinding="{Binding Path=LocationID}"
                          Header="LocationID"
                          Width="75"/>

          <GridViewColumn DisplayMemberBinding="{Binding Path=Type}"
                          Header="Type"
                          Width="50"/>

          <GridViewColumn DisplayMemberBinding="{Binding Path=Name}"
                          Header="Name"
                          Width="200"/>

          <GridViewColumn DisplayMemberBinding="{Binding Path=Enabled}"
                          Header="Enabled"
                          Width="50"/>

          <GridViewColumn DisplayMemberBinding="{Binding Path=Flags}"
                          Header="Flags"
                          Width="50"/>

        </GridView>

      </ListView.View>
    </ListView>

    <Button Name="btnOK"
            Content="OK"
            Grid.Row="1"
            Width="100"
            Height="20
            " Click="btnOK_Click" />

  </Grid>
</Window>
  • You want, get your object in he code behind, ans then, add it into your datagrid? – provençal le breton Mar 14 '13 at 14:17
  • `I've found doing simple things in XAML ++much++ more difficult and involved than doing the same thing in Winforms,` - That's because you're trying to use WPF with a winforms mentality. WPF is actually much simpler than winforms in the sense that it allows a much higher level of customization and scalability without resorting to a bunch of HACKS (such as owner draw and all that stuff). If you expect to succeed in WPF, you must understand that [UI is not Data](http://stackoverflow.com/questions/14381402/wpf-programming-methodology/14382137#14382137). – Federico Berasategui Mar 14 '13 at 15:46
  • `data binding seems to me to be a black art.` - DataBinding in WPF is far superior than (supposed) databinding in winforms. Post the code of the object you're binding to. Actually, post the entire code of your `DataContext`. – Federico Berasategui Mar 14 '13 at 15:48
  • `and tell me what I need to do or change to populate this control from my C# code-behind?` - You're not supposed to use code behind in WPF. There must be a `ViewModel` and the UI must gather its data and interact with the `ViewModel`. You must not manipulate UI elements in code. UI elements and the Visual Tree are complex things and its better to use the correct techniques than trying to manipulate these classes yourself. – Federico Berasategui Mar 14 '13 at 15:50

1 Answers1

0

I recommand to use MVVM. There you have a ViewModel class where you can have your properties to bind to.

public class MainWindowViewModel
{
    #region Constructor
    public MainWindowViewModel()
    {
        YourGridList = new ObservableCollection<GridElement>();

        var el = new GridElement
                     {
                         Element1 = "element 1", 
                         Element2 = "element 2", 
                         Element3 = "element 3"
                     };

        YourGridList.Add(el);
    }
    #endregion

    #region Private members

    private ObservableCollection<GridElement> _yourGridList;
    private ICommand _addElementCommand;

    #endregion

    #region Public properties
    public ObservableCollection<GridElement> YourGridList
    {
        get
        {
            return _yourGridList;
        }
        set
        {
            _yourGridList = value;
        }
    }
    #endregion

    #region Commands
    public ICommand AddElementCommand
    {
        get { return _addElementCommand ?? (_addElementCommand = new DelegateCommand(AddElement)); }
    }
    #endregion

    #region Private Methods
    private void AddElement()
    {
        var el = new GridElement
        {
            Element1 = "NewEl1",
            Element2 = "NewEl2",
            Element3 = "NewEl3"
        };

        YourGridList.Add(el);
    }
    #endregion

Then, you can use in the xaml.cs file this class as DataContext.

 public MainWindow()
    {
        InitializeComponent();
        DataContext = new MainWindowViewModel();
    }

And from the xaml file you can have your ListView ItemsSource populated from the "YourGridList" property from the ViewModel.

<Window x:Class="WpfApplication6.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">
<Grid>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="35"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <Button Content="Add element" Command="{Binding AddElementCommand}" Grid.Row="0"/>


        <ListView Grid.Row="1"
                  Margin="10"
                  ItemsSource="{Binding YourGridList, UpdateSourceTrigger=PropertyChanged}"
                  MaxHeight="300">
            <ListView.View>
                <GridView>
                    <GridView.Columns>
                        <GridViewColumn Width="Auto">
                            <GridViewColumn.Header>
                                <GridViewColumnHeader Content="Element 1" HorizontalContentAlignment="Left" />
                            </GridViewColumn.Header>
                            <GridViewColumn.CellTemplate>
                                <DataTemplate>
                                    <TextBlock Text="{Binding Element1}"/>
                                </DataTemplate>
                            </GridViewColumn.CellTemplate>
                        </GridViewColumn>
                        <GridViewColumn Width="Auto">
                            <GridViewColumn.Header>
                                <GridViewColumnHeader Content="Element 2" HorizontalContentAlignment="Left" />
                            </GridViewColumn.Header>
                            <GridViewColumn.CellTemplate>
                                <DataTemplate>
                                    <TextBlock Text="{Binding Element2}"/>
                                </DataTemplate>
                            </GridViewColumn.CellTemplate>
                        </GridViewColumn>
                        <GridViewColumn Width="Auto" >
                            <GridViewColumn.Header>
                                <GridViewColumnHeader Content="Element 3" HorizontalContentAlignment="Left" />
                            </GridViewColumn.Header>
                            <GridViewColumn.CellTemplate>
                                <DataTemplate>
                                    <TextBlock Text="{Binding Element3}"/>
                                </DataTemplate>
                            </GridViewColumn.CellTemplate>
                        </GridViewColumn>
                    </GridView.Columns>
                </GridView>
            </ListView.View>
        </ListView>
    </Grid>
</Grid>

This should work for updating your ListView and have a clear decoupling between the code and the xaml part.

Olimpiu Datcu
  • 156
  • 10