In WPF can I manually "reset" or re-test the triggers for a Style?
What I want to do is 're-test' a Trigger
when an event is fired. This is because the Trigger
is binding to the Row.RowState
property of a DataRowView
, which does NOT fire the PropertyChanged
notification required the for trigger to re-evaluate its condition.
(see the post at the bottom of this page: WpfToolkit DataGrid: Highlight modified rows)
I can re-set a Trigger
on a per-control basis in an event like so:
private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
Style s = ((TextBox)sender).Style;
((TextBox)sender).Style = null;
((TextBox)sender).Style = s;
}
But I have a DataGrid
with many controls and which all use one of four Style
s. What I would like to do is do something like, in psuedo code:
Style1.reTest();
Style2.reTest();
...
Is there any way to do that? The first problem is that you can't name styles, so accessing them externally to the xmlns is problematic. The second problem is that a Style
does not have a method which provides this functionality.
Any help most apppreciated.
EDIT 1: I can get the styles using the resource dictionary (can't believe I hadn't thought of it, I assumed they wouldn't be in there because I hadn't named them). If you haven't named them you can grab them like this (changing the type obviously):
Style s = (Style)Resources[typeof(System.Windows.Controls.TextBox)];
Edit2: I have found the answer and will post it when Stackoverflow allows me to. Many thanks for all the responses :)
Fugu
I know this isn't a direct answer to your question, but one possibility would be to listen to the appropriate change events coming from the DataTable and to update an attached RowState property on DataGridRow. Your DataTrigger would then use this attached RowState property. I would say this is preferable to deriving your own custom DataRowView class.
Another option would be to add an extra column to your DataTable to store the row state. Whenever the row state changes you update this value. In your DataGrid you hide this extra column but it is now available for binding to a DataTrigger
Edit: Explaining option #2 in detail
DataTable myTable
myTable.Columns.Add("Foo");
//etc etc
myTable.Columns.Add("INTERNAL_STATUS",typeof(DataRowState));
//Attach event handlers to DataTable.RowChanged, DataTable.ColumnChanged, etc
//I will just show RowChanged here
private void Row_Changed(object sender, DataRowChangeEventArgs e)
{
e.Row["INTERNAL_STATUS"] = e.Row.RowState;
}
//Now in your XAML you can use the INTERNAL_STATUS in your data trigger
Setting the TargetName should work, however it cannot work in a style. If you think about it, it makes sense: if you set the target name in the style in what scope should the runtime look for the name? So you could try to set target name but in the triggers of the element itself, not in the style.
Did it!
Let's say you have some styles in your XAML which don't have names (because you want them to apply to all controls of a particular type).
Do this to reset/re-evaluate the triggers, swapping TextBox for the appropriate type:
Style s = (Style)Resources[typeof(System.Windows.Controls.TextBox)];
Resources[typeof(System.Windows.Controls.TextBox)] = null;
Resources[typeof(System.Windows.Controls.TextBox)] = s;
Maybe it's quicker to do the same for the triggers instead of the entire Style, I would need to test this properly as it would require a loop to add the triggers back to the TriggersCollection (so it probably isn't quicker).
If you have names your styles, the key is the name as a string rather than the type the Style applies to.
If you want to highlight rows in a DataGrid when they are modified you can stick the code above in an event.
精彩评论