问题
I have created a user control, the other members of my team simply place it on their view and they can then dynamically create an ObservrableCollection of buttons and bind to it (a ribbon bar but highly customized to our needs), it handles placement, style etc. It works just fine and totally fits the need for our project however it only works upon initial load, I did some digging and realized that it was because I only had a PropertyChangedCallback in the FrameWorkMetaData and I didn't set up a callback for the CoerceValueCallback so I did some digging and set one up but I am not sure exactly what to do - I guess here is the question, the method signature of the CoerceValueCallback has it returning an object and I just want to update my buttons when ever the list changes. Is it safe to ignore this return value? Maybe some code might help -
Here is my PropertyChangedCallback - gets fired when they first assign the list of buttons
public static void ButtonListUpdated(DependencyObject source, DependencyPropertyChangedEventArgs e)
{
int count = 0;
var grid = (source as RibbonBarUserControl).ButtonsGrid;
var buttons = e.NewValue as ObservableCollection<Button>;
if (buttons != null)
{
grid.Children.Clear();
foreach (RibbonButton b in buttons)
{
b.Margin = new Thickness(1);
b.Style = (Style)grid.FindResource("ribbonButtonStyle");
ColumnDefinition c = new ColumnDefinition();
grid.ColumnDefinitions.Add(c);
grid.Children.Add(b);
Grid.SetRow(b, 0);
Grid.SetColumn(b, count);
count = ++count;
}
}
}
No here is the CoerceValueCallback
public static object OnButtonListModified(DependencyObject sender, Object baseValue)
{
//What to do here? Can I essentially ignore the returned object and basically
//copy what I am doing in ButtonListUpdated?
return baseValue;
}
I saw some examples online and they where much simpler - like if birthday is less than marriage year birthday = marriage year, course this is a little different - I am creating buttons and updating the UI of my control.
OK - Thanks for any suggestions!
回答1:
I don't think you need to use a CoerceValueCallback. Instead, you should hook into the CollectionChanged event of your collection and update your buttons when that is fired.
So something like:
public static void ButtonListUpdated(DependencyObject source, DependencyPropertyChangedEventArgs e)
{
var control = source as RibbonBarUserControl;
var buttons = e.OldValue as ObservableCollection<Button>;
if (buttons != null)
buttons.CollectionChanged -= control.OnCollectionChanged;
buttons = e.NewValue as ObservableCollection<Button>;
if (buttons != null)
buttons.CollectionChanged += control.OnCollectionChanged;
control.UpdateButtons();
}
private void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
this.UpdateButtons();
}
private void UpdateButtons() {
// TODO: Update buttons
}
You could also use the members of NotifyCollectionChangedEventArgs
to determine how the collection changed, and make minimal changes to buttons. Or you could just completely rebuild them everytime.
来源:https://stackoverflow.com/questions/6845405/how-to-propertly-use-coercevaluecallback-in-a-custom-wpf-usercontrol