none
DataGridのToolTipの表示・非表示の設定 RRS feed

  • 質問

  • DataGridの特定の列にToolTipを表示させるようにしたんですが、

    ボタンを追加してボタンをクリックしたらToolTipを表示する、もう一度ボタンをクリックしたら表示しないというふうに切り替えたいです。

    どうすればよいでしょうか?

    環境はVisual Studio 2010です。

    コードは以下のように記述しています。

    MainWindow.xaml

    <DataGrid AutoGenerateColumns="False" Name="dataGrid1">
    	<DataGrid.Columns>
    		<DataGridTemplateColumn Header="First Name">
    			<DataGridTemplateColumn.CellTemplate>
    				<DataTemplate>
    					<TextBlock Text="{Binding FirstName}">
    						<TextBlock.ToolTip>
    							<TextBlock Text="{Binding FirstName}"/>
    						</TextBlock.ToolTip>
    					</TextBlock>
    				</DataTemplate>
    			</DataGridTemplateColumn.CellTemplate>
    		</DataGridTemplateColumn>
    		<DataGridTextColumn Header="Last Name" Binding="{Binding LastName}"/>
    		<DataGridTextColumn Header="Email ID" Binding="{Binding EmailID}"/>
    		<DataGridTextColumn Header="Contact" Binding="{Binding Contact}"/>
    	</DataGrid.Columns>
    </DataGrid>
    
    

    MainWindow.xaml.cs

    namespace TooltipInDataGrid
    {
    	public class Employee
    	{
    		public string FirstName { get; set; }
    		public string LastName { get; set; }
    		public string EmailID { get; set; }
    		public string Contact { get; set; }
    	}
    
    	/// <summary>
    	/// MainWindow.xaml の相互作用ロジック
    	/// </summary>
    	public partial class MainWindow : Window
    	{
    		public MainWindow()
    		{
    			InitializeComponent();
    
    			ObservableCollection<Employee> empList = new ObservableCollection<Employee>();
    			for (int i = 1; i < 20; i++)
    			{
    				Employee emp = new Employee
    				{
    					FirstName="FirstName"+i.ToString(),
    					LastName = "LastName"+i.ToString(),
    					EmailID = "EmailID"+i.ToString(),
    					Contact = "Contact"+i.ToString(),
    				};
    
    				empList.Add(emp);
    			}
    			dataGrid1.ItemsSource = empList;
    		}
    	}
    }
    
    • 編集済み yty0918 2010年5月14日 8:12
    2010年5月14日 7:58

回答

  • バインディングするオブジェクトに bool 型のプロパティを追加(INotifyPropertyChanged による変更イベントを実装)。

    直接 TextBlock.ToolTip を設定するのはやめて、TextBlock.Style の Triggers に DataTrigger を追加し上記プロパティが true になったときの Setter にて ToolTip を設定する。

    あとはボタン押下時にこのプロパティを切り替える。

    という手順になるかと思いますが。

    • 回答としてマーク 山本春海 2010年5月19日 8:48
    2010年5月14日 8:11
  • あまりいいやり方じゃないかもしれませんが、以下のようにC#側でツールチップの切り替えをすることにしました。

    <DataGrid AutoGenerateColumns="False" Name="dataGrid1" Margin="0,0,0,41">
    	<DataGrid.Columns>
    		<DataGridTemplateColumn Header="First Name">
    			<DataGridTemplateColumn.CellTemplate>
    				<DataTemplate>
    					<TextBlock Text="{Binding FirstName}"/>
    				</DataTemplate>
    			</DataGridTemplateColumn.CellTemplate>
    		</DataGridTemplateColumn>
    		<DataGridTextColumn Header="Last Name" Binding="{Binding LastName}"/>
    		<DataGridTextColumn Header="Email ID" Binding="{Binding EmailID}"/>
    		<DataGridTextColumn Header="Contact" Binding="{Binding Contact}"/>
    	</DataGrid.Columns>
    </DataGrid>
    <Button Height="23" HorizontalAlignment="Left" Margin="416,276,0,0" Name="button1" VerticalAlignment="Top" Width="75" 
    		Click="button1_Click" Content="button1" />

     

    namespace TooltipInDataGrid
    {	
    	/// <summary>
    	/// MainWindow.xaml の相互作用ロジック
    	/// </summary>
    	public partial class MainWindow : Window
    	{
    		public bool IsTooltip { get; set; }
    
    		public MainWindow()
    		{
    			InitializeComponent();
    
    			ObservableCollection<Employee> empList = new ObservableCollection<Employee>();
    			for (int i = 1; i < 20; i++)
    			{
    				Employee emp = new Employee
    				{
    					FirstName = "FirstName" + i.ToString(),
    					LastName = "LastName" + i.ToString(),
    					EmailID = "EmailID" + i.ToString(),
    					Contact = "Contact" + i.ToString(),
    				};
    				empList.Add(emp);
    			}
    
    			dataGrid1.ItemsSource = empList;
    		}
    
    		private void button1_Click(object sender, RoutedEventArgs e)
    		{
    			if (IsTooltip)
    			{
    				dataGrid1.Columns[0].CellStyle = null;
    				IsTooltip = !IsTooltip;
    			}
    			else
    			{
    				Style style = new Style();
    				style.Setters.Add(new Setter(TextBlock.ToolTipProperty, new Binding("FirstName")));
    				dataGrid1.Columns[0].CellStyle = style;
    				IsTooltip = !IsTooltip;
    			}
    		}
    	}
    
    	public class Employee
    	{
    		public string FirstName { get; set; }
    		public string LastName { get; set; }
    		public string EmailID { get; set; }
    		public string Contact { get; set; }
    	}
    }
    

     

    おそらく、button1_Clickのif文がDataTriggerにあたると思うのですが、DataTriggerの動作が不明確のためこのようにしました。

    Hongliangさんありがとうございました。

    • 回答としてマーク 山本春海 2010年5月19日 8:48
    2010年5月17日 5:50

すべての返信

  • バインディングするオブジェクトに bool 型のプロパティを追加(INotifyPropertyChanged による変更イベントを実装)。

    直接 TextBlock.ToolTip を設定するのはやめて、TextBlock.Style の Triggers に DataTrigger を追加し上記プロパティが true になったときの Setter にて ToolTip を設定する。

    あとはボタン押下時にこのプロパティを切り替える。

    という手順になるかと思いますが。

    • 回答としてマーク 山本春海 2010年5月19日 8:48
    2010年5月14日 8:11
  • 回答ありがとうございます。

    上記の回答を元にコーディングしようと思いますが、INotifyPropertyChangedやDataTriggerなど知らなかった言葉もあるので調査します。

    2010年5月17日 1:32
  • 下記のようにコーディングしてみましたが、うまくいきません。

    <DataGrid AutoGenerateColumns="False" Name="dataGrid1" Margin="0,0,0,41">
    	<DataGrid.Columns>
    		<DataGridTemplateColumn Header="First Name">
    			<DataGridTemplateColumn.CellTemplate>
    				<DataTemplate>
    					<TextBlock Text="{Binding FirstName}">
    						<TextBlock.Style>
    							<Style TargetType="{x:Type TextBlock}">
    								<Style.Triggers>
    									<DataTrigger Binding="{Binding IsTooltip}" Value="true">
    										<Setter Property="ToolTip" Value="{Binding FirstName}"/>
    									</DataTrigger>
    								</Style.Triggers>
    							</Style>
    						</TextBlock.Style>
    						<!--<TextBlock.ToolTip>
    							<TextBlock Text="{Binding FirstName}"/>
    						</TextBlock.ToolTip>-->
    					</TextBlock>
    				</DataTemplate>
    			</DataGridTemplateColumn.CellTemplate>
    		</DataGridTemplateColumn>
    		<DataGridTextColumn Header="Last Name" Binding="{Binding LastName}"/>
    		<DataGridTextColumn Header="Email ID" Binding="{Binding EmailID}"/>
    		<DataGridTextColumn Header="Contact" Binding="{Binding Contact}"/>
    	</DataGrid.Columns>
    </DataGrid>
    <Button Content="Button" Height="23" HorizontalAlignment="Left" Margin="416,276,0,0" Name="button1" VerticalAlignment="Top" Width="75" 
    		Click="button1_Click"/>
    

     

    namespace TooltipInDataGrid
    {	
    	/// <summary>
    	/// MainWindow.xaml の相互作用ロジック
    	/// </summary>
    	public partial class MainWindow : Window, INotifyPropertyChanged
    	{
    		private bool isTooltip;
    		public bool IsTooltip
    		{
    			get { return isTooltip; }
    			set
    			{
    				this.isTooltip = value;
    				OnPropertyChanged("Tooltip");
    			}
    		} 
    
    		public event PropertyChangedEventHandler PropertyChanged;
    		protected void OnPropertyChanged(string tooltip)
    		{
    			if (PropertyChanged != null)
    			{
    				PropertyChanged(this, new PropertyChangedEventArgs(tooltip));
    			}
    		} 
    
    		public MainWindow()
    		{
    			InitializeComponent();
    
    			ObservableCollection<Employee> empList = new ObservableCollection<Employee>();
    			for (int i = 1; i < 20; i++)
    			{
    				Employee emp = new Employee
    				{
    					FirstName = "FirstName" + i.ToString(),
    					LastName = "LastName" + i.ToString(),
    					EmailID = "EmailID" + i.ToString(),
    					Contact = "Contact" + i.ToString(),
    				};
    				empList.Add(emp);
    			}
    
    			dataGrid1.ItemsSource = empList;
    		}
    
    		private void button1_Click(object sender, RoutedEventArgs e)
    		{
    			IsTooltip = !IsTooltip;
    		}
    	}
    
    	public class Employee
    	{
    		public string FirstName { get; set; }
    		public string LastName { get; set; }
    		public string EmailID { get; set; }
    		public string Contact { get; set; }
    	}
    }
    

    OnPropertyChangedでPropertyChangedがnullになっているため、

    PropertyChanged(this, new PropertyChangedEventArgs(tooltip));

    が実行されません。

    どこに問題があるのでしょうか?

    2010年5月17日 2:39
  • まず確認する必要がありますが、ツールチップを表示するかどうかはこの DataGrid 全体で一意なんですね? つまり、この行は表示しない、この行は表示する、というものではないと。前回の私の投稿は少し読み違いしていたようです。

    さて、DataTemplate 内では、DataContext は DataGrid.ItemsSource に設定したコレクションの各要素になります。今回の場合だとそれぞれの Employee が DataContext ですね。

    さて、Binding は、Source や RelativeSource や ElementName が明示されない場合、DataContext のオブジェクトをバインディングソースとします。TextBlock の Text に {Binding FirstName} と書けば Employee.FirstName のことを指すことから明らかですね。当然それは DataTrigger の Binding も同じです。つまり、DataTrigger の Binding もソースが明示されていない以上 Employee をバインディングソースとして認識し、その IsToolTip プロパティを参照しようとし、見つからずに諦めているわけです。

    MainWindow に IsToolTip プロパティを用意するなら、DataTrigger のバインディングソースを明示的に MainWindow に設定する必要があります。手っ取り早いのは、<Window> 要素に Name 属性を付け、DataTrigger の Binding において ElementName でその名前を指定することですね。

    あと、MainWindow にプロパティを用意するなら、INotifyPropertyChanged ではなく依存関係プロパティとして定義する方が良いかもしれません。MSDN やヘルプで「カスタム依存関係プロパティ」というページを調べてみて下さい。

    2010年5月17日 3:44
  • あまりいいやり方じゃないかもしれませんが、以下のようにC#側でツールチップの切り替えをすることにしました。

    <DataGrid AutoGenerateColumns="False" Name="dataGrid1" Margin="0,0,0,41">
    	<DataGrid.Columns>
    		<DataGridTemplateColumn Header="First Name">
    			<DataGridTemplateColumn.CellTemplate>
    				<DataTemplate>
    					<TextBlock Text="{Binding FirstName}"/>
    				</DataTemplate>
    			</DataGridTemplateColumn.CellTemplate>
    		</DataGridTemplateColumn>
    		<DataGridTextColumn Header="Last Name" Binding="{Binding LastName}"/>
    		<DataGridTextColumn Header="Email ID" Binding="{Binding EmailID}"/>
    		<DataGridTextColumn Header="Contact" Binding="{Binding Contact}"/>
    	</DataGrid.Columns>
    </DataGrid>
    <Button Height="23" HorizontalAlignment="Left" Margin="416,276,0,0" Name="button1" VerticalAlignment="Top" Width="75" 
    		Click="button1_Click" Content="button1" />

     

    namespace TooltipInDataGrid
    {	
    	/// <summary>
    	/// MainWindow.xaml の相互作用ロジック
    	/// </summary>
    	public partial class MainWindow : Window
    	{
    		public bool IsTooltip { get; set; }
    
    		public MainWindow()
    		{
    			InitializeComponent();
    
    			ObservableCollection<Employee> empList = new ObservableCollection<Employee>();
    			for (int i = 1; i < 20; i++)
    			{
    				Employee emp = new Employee
    				{
    					FirstName = "FirstName" + i.ToString(),
    					LastName = "LastName" + i.ToString(),
    					EmailID = "EmailID" + i.ToString(),
    					Contact = "Contact" + i.ToString(),
    				};
    				empList.Add(emp);
    			}
    
    			dataGrid1.ItemsSource = empList;
    		}
    
    		private void button1_Click(object sender, RoutedEventArgs e)
    		{
    			if (IsTooltip)
    			{
    				dataGrid1.Columns[0].CellStyle = null;
    				IsTooltip = !IsTooltip;
    			}
    			else
    			{
    				Style style = new Style();
    				style.Setters.Add(new Setter(TextBlock.ToolTipProperty, new Binding("FirstName")));
    				dataGrid1.Columns[0].CellStyle = style;
    				IsTooltip = !IsTooltip;
    			}
    		}
    	}
    
    	public class Employee
    	{
    		public string FirstName { get; set; }
    		public string LastName { get; set; }
    		public string EmailID { get; set; }
    		public string Contact { get; set; }
    	}
    }
    

     

    おそらく、button1_Clickのif文がDataTriggerにあたると思うのですが、DataTriggerの動作が不明確のためこのようにしました。

    Hongliangさんありがとうございました。

    • 回答としてマーク 山本春海 2010年5月19日 8:48
    2010年5月17日 5:50