我有以下方法向ViewModel事件注册进度条UserControl:
private void SetProgressBar(ProgressBar progressBar)
{
_progressBar = progressBar;
_progressBar.SizeChanged += (s, e) => ComputeViewModelProperties();
RegisterForNotification("Value", progressBar, (d, e) => ComputeViewModelProperties());
RegisterForNotification("Maximum", progressBar, (d, e) => ComputeViewModelProperties());
RegisterForNotification("Minimum", progressBar, (d, e) => ComputeViewModelProperties());
ComputeViewModelProperties();
}
private void RegisterForNotification(string propertyName, FrameworkElement element, PropertyChangedCallback callback)
{
//Bind to a dependency property
Binding b = new Binding(propertyName) { Source = element };
Prop = System.Windows.DependencyProperty.RegisterAttached(
"ListenAttached" + propertyName,
typeof(object),
typeof(UserControl),
new PropertyMetadata(callback));
element.SetBinding(Prop, b);
}
当我第一次将ProgressBar控件添加到XAML时,我没有收到任何错误。但是,在编辑XAML以添加其他控件时,我剪切并粘贴了ProgressBar以移动它,并收到错误:
ArgumentException: 'ListenAttachedValue' property was already registered by 'UserControl'.
为什么删除和添加此控件会导致错误?为什么它在第一次实施时没有引起问题?如果没有相应的错误注册"最大"和"最低?"
我的XAML:
<ProgressBar Value="{Binding Value}"
Width="80" Height="80"
Grid.Row="1" Grid.Column="1"
Style="{StaticResource SegmentedProgressBarStyle}" />
编辑:来自源代码的更多代码
public static CircularProgressBarViewModel GetAttach(DependencyObject d)
{
return (CircularProgressBarViewModel)d.GetValue(AttachProperty);
}
public static void SetAttach(DependencyObject d, CircularProgressBarViewModel value)
{
d.SetValue(AttachProperty, value);
}
/// <summary>
/// Change handler for the Attach property
/// </summary>
private static void OnAttachChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
// set the view model as the DataContext for the rest of the template
FrameworkElement targetElement = d as FrameworkElement;
CircularProgressBarViewModel viewModel = e.NewValue as CircularProgressBarViewModel;
targetElement.DataContext = viewModel;
// handle the loaded event
targetElement.Loaded += new RoutedEventHandler(Element_Loaded);
}
/// <summary>
/// Handle the Loaded event of the element to which this view model is attached
/// in order to enable the attached
/// view model to bind to properties of the parent element
/// </summary>
static void Element_Loaded(object sender, RoutedEventArgs e)
{
FrameworkElement targetElement = sender as FrameworkElement;
CircularProgressBarViewModel attachedModel = GetAttach(targetElement);
// find the ProgressBar and associated it with the view model
var progressBar = targetElement.Ancestors<ProgressBar>().Single() as ProgressBar;
attachedModel.SetProgressBar(progressBar);
}
答案 0 :(得分:0)
我解决了这个特殊问题:
public static DependencyProperty AttachedProperty;
由于该属性已注册一次,我只是重用它来绑定回调。
private void RegisterForNotification(string propertyName, FrameworkElement element, PropertyChangedCallback callback)
{
//Bind to a dependency property
Binding b = new Binding(propertyName) { Source = element };
if (AttachedProperty == null)
{
AttachedProperty = DependencyProperty.RegisterAttached(
"ListenAttached" + propertyName,
typeof(object),
typeof(MainWindow),
new PropertyMetadata(callback));
}
element.SetBinding(AttachedProperty, b);
}
不幸的是,这个Silverlight项目还有一些工作要先在你的WPF应用程序中使用它,我想这是我们的共同目标。