DispatcherTimer
リソースが多すぎて困っています。誰かが助けてくれることを願っています。
XAML を使用して画面にアイテムのリストを表示しています。リストの各行には、その行の情報を変更するボタンがあります。コード ビハインドでは、リストのどの行がクリックされたかを判断する必要があります。これは、壊れているコードの魔法の部分です。
int row_index = DataGridRow.GetRowContainingElement(sender as FrameworkElement).GetIndex();
row_index が正しく設定されている場合もあれば、-1 が返される場合もあります。常に正しいインデックスを返さないのはなぜですか? さらに不満を募らせたのは、デバッガーを使用して DataGridRow 構造の正しいインデックスを確認できることです。正しいインデックスはありますが、GetIndex()
それでも -1 が返されることがあります。
インターフェイス コード:
<Window x:Class="WhyNoButtonClick.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="WhyNoButtonClick" Height="265" Width="306">
<Grid Margin="0,0,0,1">
<StackPanel Height="192" VerticalAlignment="Top">
<DataGrid x:Name="dg_driver_list" AutoGenerateColumns="False" Height="186">
<DataGrid.Columns>
<DataGridTemplateColumn Header="Name">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Label x:Name="col_driver_name" Content="{Binding Name}" TextBlock.LineStackingStrategy="BlockLineHeight" TextBlock.LineHeight="5" FontSize="12"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Time remaining">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Label x:Name="col_driver_time_remain" Content="{Binding TimeRemain}" TextBlock.LineStackingStrategy="BlockLineHeight" TextBlock.LineHeight="5" FontSize="12"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Action button">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button x:Name="btn_driver_hit" PreviewMouseDown="btn_driver_hit_Click" Content="Hit" Height="20" TextBlock.LineStackingStrategy="BlockLineHeight" TextBlock.LineHeight="5" FontSize="12"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</StackPanel>
<StackPanel Margin="105,192,105,10">
<Button x:Name="btn_pause_active" Content="Start/Pause" ToolTip="Start/Pause stopwatches for all active drivers" Height="22" Click="btn_start_pause_active_Click"/>
</StackPanel>
</Grid>
</Window>
分離コード:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Diagnostics;
using System.Windows.Threading;
using System.Windows.Media;
namespace WhyNoButtonClick
{
public partial class MainWindow : Window
{
// ### Modify this to increase or decrease the chances of getting the correct index.
TimeSpan screen_refresh_delay = new TimeSpan(0, 0, 0, 0, 025);
DispatcherTimer update_timer_dispatch = new DispatcherTimer(DispatcherPriority.Normal);
List<Stopwatch> driver_hit_timer_watches = new List<Stopwatch>();
List<Participant> driver_list = new List<Participant>();
SolidColorBrush color_red = new SolidColorBrush(Color.FromRgb(255, 0, 0)); // Red
SolidColorBrush color_black = new SolidColorBrush(Color.FromRgb(0, 0, 0)); // Black
TimeSpan hit_timer = new TimeSpan(0, 0, 60);
TimeSpan time_almost_up = new TimeSpan(0, 0, 0, 59);
TimeSpan time_remaining = new TimeSpan(0, 0, 0);
public MainWindow()
{
InitializeComponent();
Label driver_name_01 = new Label();
Label driver_time_remain_01 = new Label();
driver_name_01.Content = "adam (1)";
Label driver_name_02 = new Label();
Label driver_time_remain_02 = new Label();
driver_name_02.Content = "ben (2)";
Label driver_name_03 = new Label();
Label driver_time_remain_03 = new Label();
driver_name_03.Content = "chad (3)";
driver_list.Add(new Participant(0, driver_name_01, driver_time_remain_01));
driver_list.Add(new Participant(1, driver_name_02, driver_time_remain_02));
driver_list.Add(new Participant(2, driver_name_03, driver_time_remain_03));
for (Int16 driver_index = 0; driver_index < driver_list.Count; driver_index++)
{
driver_hit_timer_watches.Add(new Stopwatch());
driver_hit_timer_watches[driver_index].Stop();
driver_hit_timer_watches[driver_index].Reset();
}
dg_driver_list.ItemsSource = driver_list;
update_timer_dispatch.Interval = screen_refresh_delay;
update_timer_dispatch.Tick += new EventHandler(update_timer_dispatch_tick);
update_timer_dispatch.Start();
}
void update_timer_dispatch_tick(object sender, EventArgs e)
{
for (Int16 driver_index = 0; driver_index < driver_hit_timer_watches.Count; driver_index++)
{
time_remaining = hit_timer - driver_hit_timer_watches[driver_index].Elapsed;
if (time_remaining.CompareTo(time_almost_up) < 0)
{
driver_list[driver_index].Name.Foreground = color_black;
driver_list[driver_index].TimeRemain.Foreground = color_black;
}
driver_list[driver_index].TimeRemain.Content = String.Format("{0:0}:{1:00}.{2:0}", time_remaining.Minutes.ToString(), time_remaining.Seconds.ToString(), (time_remaining.Milliseconds / 100).ToString());
}
dg_driver_list.Items.Refresh();
}
private void btn_driver_hit_Click(object sender, RoutedEventArgs e)
{
int row_index = DataGridRow.GetRowContainingElement(sender as FrameworkElement).GetIndex();
if (row_index > -1)
{
driver_list[row_index].Name.Foreground = color_red;
driver_list[row_index].TimeRemain.Foreground = color_red;
if (driver_hit_timer_watches[row_index].IsRunning)
{
driver_hit_timer_watches[row_index].Restart();
}
else
{
driver_hit_timer_watches[row_index].Reset();
}
}
else
{
// I need to know what row to modify but don't have an index!
// ### Debug - Breakpoint here.
DataGridRow myrow = DataGridRow.GetRowContainingElement(sender as FrameworkElement);
int myindex = myrow.GetIndex();
}
}
private void btn_start_pause_active_Click(object sender, RoutedEventArgs e)
{
for (Int16 driver_index = 0; driver_index < driver_hit_timer_watches.Count; driver_index++)
{
if (driver_hit_timer_watches[driver_index].IsRunning)
{
driver_hit_timer_watches[driver_index].Stop();
}
else
{
driver_hit_timer_watches[driver_index].Start();
}
}
}
}
public class Participant
{
public Int16 Index { get; set; }
public Label Name { get; set; }
public Label TimeRemain { get; set; }
public Participant(Int16 index, Label name, Label timeRemain)
{
this.Index = index;
this.Name = name;
this.TimeRemain = timeRemain;
}
}
}
何か案は?
注: コードで "###" (トリプル ポンド) を検索して、ブレークポイントを配置した場所を確認します。