Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>If I understand correctly, you have a collection of items and you have a couple fields (bid/ask in particular), all of which will be updated every second. It sounds like what may be happening is that in the process of changing the ItemsSource of your data grid, you're losing some important state that is causing problems for the event handlers on your buttons.</p> <p>Even if you update all of the items, the important distinction to make is that you should update the items, and not completely clear out the collection that is currently bound to your datagrid. Changing the ItemsSource to a new one will cause the data grid to have to do a lot more work than if you simply update the contents of the existing collection. If you're using an ObservableCollection, this may mean making your viewmodel items mutable so that you can simply update bid/ask. If your viewmodel items are mutable and implement INotifyPropertyChanged, the bid/ask updates will be reflected in the datagrid or in any other bindings to those properties of the objects. The neat thing about doing it this way is that the same objects are staying bound to the same containers in the ItemsControl, so during each update, absolutely nothing is happening to your buttons. Now, if your viewmodel objects that contain bid/ask are immutable, you should still be able to pull this off. Every second, you simply iterate through your collection of items and use SetItem to replace each existing item with a new one. The important thing to remember in this latter case is that every second, the datagrid is still getting notified that there has been a change in the ObservableCollection, and because of this, the bindings on each row are going to cause the DataContext of the row/cells/button to update. </p> <p>Here's a quick example of how I might go about this problem. I'm going to assume use of the datagrid in .NET 4.0 (if you're using toolkit though with 3.5, this should be the same). I'm going to take the first approach, where my CurrencyPair object is mutable. </p> <p>First, some simple viewmodel code with a self contained timer to update a few currency pair bid/asks each second:</p> <pre><code>public class CurrencyPairsViewModel { private readonly Dispatcher _dispatcher = Dispatcher.CurrentDispatcher; private readonly ObservableCollection&lt;string&gt; _orders = new ObservableCollection&lt;string&gt;(); private readonly ObservableCollection&lt;CurrencyPair&gt; _pairs = new ObservableCollection&lt;CurrencyPair&gt;(); private readonly Random _rand = new Random(); private readonly System.Timers.Timer _timer = new System.Timers.Timer(1000); private readonly Action _update; public CurrencyPairsViewModel() { this._timer.Elapsed += OnIntervalElapsed; this._update = new Action(this.Update); this._pairs.Add(new CurrencyPair("USD/GBP")); this._pairs.Add(new CurrencyPair("AUD/USD")); this._pairs.Add(new CurrencyPair("WOW/CAD")); this._timer.Start(); } public ObservableCollection&lt;string&gt; Orders { get { return this._orders; } } public ObservableCollection&lt;CurrencyPair&gt; Pairs { get { return this._pairs; } } public void Buy(CurrencyPair pair) { this._orders.Add(string.Format("Buy {0} at {1}", pair.Name, pair.Ask)); } private void OnIntervalElapsed(object sender, System.Timers.ElapsedEventArgs e) { this._dispatcher.Invoke(this._update); } private void Update() { foreach (var pair in this._pairs) { pair.Bid = this._rand.NextDouble(); pair.Ask = pair.Bid + 0.01; } this._timer.Start(); } } public class CurrencyPair : INotifyPropertyChanged { private readonly string _name; private double _ask; private double _bid; public CurrencyPair(string name) { this._name = name; } public event PropertyChangedEventHandler PropertyChanged; public double Ask { get { return this._ask; } set { this._ask = value; this.OnPropertyChanged("Ask"); } } public double Bid { get { return this._bid; } set { this._bid = value; this.OnPropertyChanged("Bid"); } } public string Name { get { return this._name; } } protected void OnPropertyChanged(string name) { if (null != this.PropertyChanged) { this.PropertyChanged(this, new PropertyChangedEventArgs(name)); } } } </code></pre> <p>Second, the view, which in this example is just my MainWindow.</p> <pre><code>&lt;Window x:Class="WpfApplication1.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"&gt; &lt;Grid&gt; &lt;Grid.RowDefinitions&gt; &lt;RowDefinition Height="*"/&gt; &lt;RowDefinition Height="4"/&gt; &lt;RowDefinition Height="*"/&gt; &lt;/Grid.RowDefinitions&gt; &lt;DataGrid Grid.Row="0" ItemsSource="{Binding Pairs}" AutoGenerateColumns="False"&gt; &lt;DataGrid.Columns&gt; &lt;DataGridTextColumn Header="Name" Binding="{Binding Name}" Width="*"/&gt; &lt;DataGridTextColumn Header="Bid" Binding="{Binding Bid}" Width="*"/&gt; &lt;DataGridTextColumn Header="Ask" Binding="{Binding Ask}" Width="*"/&gt; &lt;DataGridTemplateColumn Header="Buy"&gt; &lt;DataGridTemplateColumn.CellTemplate&gt; &lt;DataTemplate&gt; &lt;Button Content="BUY" Click="OnBuyClicked"/&gt; &lt;/DataTemplate&gt; &lt;/DataGridTemplateColumn.CellTemplate&gt; &lt;/DataGridTemplateColumn&gt; &lt;/DataGrid.Columns&gt; &lt;/DataGrid&gt; &lt;GridSplitter Grid.Row="1" Height="4" HorizontalAlignment="Stretch" VerticalAlignment="Center"/&gt; &lt;ListBox Grid.Row="2" ItemsSource="{Binding Orders}"/&gt; &lt;/Grid&gt; &lt;/Window&gt; </code></pre> <p>And finally, I have a bit of code behind this XAML to handle the BUY button clicks and initialize a viewmodel right in the view (note that this, and other practices outside of how to update the bid/ask on the collection of items may not be the best way to go about things, depending on how your application is going to grow). </p> <pre><code>public partial class MainWindow : Window { private readonly CurrencyPairsViewModel _model = new CurrencyPairsViewModel(); public MainWindow() { InitializeComponent(); this.DataContext = this._model; } private void OnBuyClicked(object sender, RoutedEventArgs e) { var pair = (CurrencyPair)((Button)sender).DataContext; this._model.Buy(pair); } } </code></pre> <p>Hope the example is helpful! </p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload