WPF data binding to a data model as an application resource

I have have a problem with data binding. I have defined a application resource in XAML like this:

<Application.Resources>
   <local:DataModel x:Key="myDataModel"/>
</Application.Resources>

I bound that model to a list, like this:

<ListView Name="ListBox" 
          ItemsSource="{Binding Source={StaticResource myDataModel}, Path=StatusList}" 
          HorizontalAlignment="Left" 
          HorizontalContentAlignment="Left" 
          VerticalContentAlignment="Top" 
          BorderThickness="0" 
          Background="#000000">
    <ListView.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel Orientation="Horizontal"></StackPanel>
        </ItemsPanelTemplate>
    </ListView.ItemsPanel>

    <ListView.ItemTemplate>
        <DataTemplate>
            <Button MinWidth="20" 
                    MinHeight="100" 
                    Background="{Binding Converter={StaticResource StatusConverter}}" 
                    Content="{Binding}" />
        </DataTemplate>
     </ListView.ItemTemplate>
</ListView>

the problem now is that if I change the values of the application resource after binding, the list is not updated. It seems like the binding is done using a copy instead of a reference. The data of the model is updated fine, the PropertyChanged event is raised but the data inside the list never changes.

For your understanding: I have a network client who receives new data every 10 seconds that data needs to be drawn in that list. Right now whenever I receive data, I update the application resource, which as I said should be bound to the list. When I debug the code stopping right in front of the InitializeComponent() method of the XAML file containing the list and wait for a few seconds, I get the latest results of the data transferred, but thats it, it is never updated again.

Can you tell me a better way of defining a globally available instance of my model or a better way of binding it? As you see I need it in more than one part of my program.

Answers


public class DataModel
{
  private IObservableCollection<short> this.statusList;
  public IObservableCollection<short> StatusList
  {
    get {
      return this.statusList;
    }
    set {
      this.statusList = value;
      this.RaisePropertyChanged("StatusList");
    }
  } 
}

now you can do this one

this.StatusList = new ObservableCollection<short>();

hope this helps

EDIT

Here is an example that I am running without any problems.

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

  <Window.Resources>
    <local:DataModel x:Key="myDataModel" />
    <local:StatusConverter x:Key="StatusConverter" />
  </Window.Resources>

  <Grid>

    <Grid.RowDefinitions>
      <RowDefinition Height="Auto" />
      <RowDefinition />
    </Grid.RowDefinitions>

    <Button Grid.Row="0"
            Content="Update"
            Click="Button_Click" />

    <ListView Name="ListBox"
              Grid.Row="1"
              ItemsSource="{Binding Source={StaticResource myDataModel}, Path=StatusList}"
              HorizontalAlignment="Left"
              HorizontalContentAlignment="Left"
              VerticalContentAlignment="Top"
              BorderThickness="0"
              Background="#000000">
      <ListView.ItemsPanel>
        <ItemsPanelTemplate>
          <StackPanel Orientation="Horizontal"></StackPanel>
        </ItemsPanelTemplate>
      </ListView.ItemsPanel>

      <ListView.ItemTemplate>
        <DataTemplate>
          <Button MinWidth="20"
                  MinHeight="100"
                  Background="{Binding Converter={StaticResource StatusConverter}}"
                  Content="{Binding}"></Button>
        </DataTemplate>
      </ListView.ItemTemplate>
    </ListView>

  </Grid>
</Window>

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
using System.Windows.Media;

namespace WpfStackOverflowSpielWiese
{
  /// <summary>
  /// Interaction logic for Window1.xaml
  /// </summary>
  public partial class Window1 : Window
  {
    public Window1() {
      this.InitializeComponent();
    }

    private void Button_Click(object sender, RoutedEventArgs e) {
      var dataModel = this.TryFindResource("myDataModel") as DataModel;
      if (dataModel != null) {
        dataModel.UpdateStatusList(new[] {(short)1, (short)2, (short)3});
      }
    }
  }

  public class DataModel : INotifyPropertyChanged
  {
    private ObservableCollection<short> statusList;

    public DataModel() {
      this.StatusList = new ObservableCollection<short>();

      this.UpdateStatusList(new[] {(short)1, (short)2, (short)3});
    }

    public void UpdateStatusList(IEnumerable<short> itemsToUpdate) {
      foreach (var s in itemsToUpdate) {
        this.StatusList.Add(s);
      }
    }

    public ObservableCollection<short> StatusList {
      get { return this.statusList; }
      set {
        this.statusList = value;
        this.RaisePropertyChanged("StatusList");
      }
    }

    private void RaisePropertyChanged(string propertyName) {
      var eh = this.PropertyChanged;
      if (eh != null) {
        eh(this, new PropertyChangedEventArgs(propertyName));
      }
    }

    public event PropertyChangedEventHandler PropertyChanged;
  }

  public class StatusConverter : IValueConverter
  {
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
      if (value is short) {
        switch ((short)value) {
          case 1:
            return Brushes.Red;
          case 2:
            return Brushes.Orange;
          case 3:
            return Brushes.Green;
        }
      }
      return Brushes.White;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
      return DependencyProperty.UnsetValue;
    }
  }
}

I have solved the problem. I have altered the values inside the list. But what I needed to do was create a new one and add the new values. All I needed to do was add this line:

this.StatusList = new IObservableCollection<short>()

and instead of doing it like this:

for(int i=0; i<ListSize; i++)
    StatusList[i] = i;

i had to do:

for(int i=0; i<ListSize; i++)
    StatusList.add( i );

You also need a little workaround from here: Problem with ListBoxItem - produce "System.Windows.Data Error: 4"

The surronding element needs to set the alignment properties using styles like this:

<Style TargetType="{x:Type ListBoxItem}">
    <Setter Property="HorizontalContentAlignment" Value="Left" />
    <Setter Property="VerticalContentAlignment" Value="Top" />
</Style>

This way you can avoid the System.Windows.Data Error 4 exceptions

again thanks to everyone who answered! :)


Need Your Help

using join in case sql

sql left-join case

i am trying to make a query but it is not right.

Getting a button to disappear when a text field is done editing, but switches to another text field

objective-c uibutton uitextfield

My UIButton is set to disappear every time my UITextField is done editing, I invoke the textFieldDidEndEditing: method, and just have the button fade away. This works fine, unless I switch to anot...

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.