public static void Bind(object viewModel, DependencyObject view, object context) { var viewModelType = viewModel.GetType(); var elements = view.Descendants <FrameworkContentElement>() .Where(e => !string.IsNullOrEmpty(e.Name)) .Distinct() .ToList(); foreach (var element in elements) { var convention = ConventionManager.GetElementConvention(element.GetType()); if (convention == null) { continue; } PropertyInfo property; Type resultViewModelType; var bindPath = NotifyValueSupport.Patch(viewModelType, element.Name, out property, out resultViewModelType); if (property == null) { continue; } Bind(convention, element, bindPath, property, viewModelType); } }
public static void Register() { ConventionManager.ApplyValueConverter = ApplyValueConverter; ConventionManager.AddElementConvention <SplitButton>(ContentControl.ContentProperty, "DataContext", "Click"); ConventionManager.AddElementConvention <Run>(Run.TextProperty, "Text", "DataContextChanged"); ConventionManager.AddElementConvention <IntegerUpDown>(UpDownBase <int?> .ValueProperty, "Value", "ValueChanged"); ConventionManager.AddElementConvention <FlowDocumentScrollViewer>(FlowDocumentScrollViewer.DocumentProperty, "Document ", "DataContextChanged"); ConventionManager.AddElementConvention <DocumentViewerBase>(DocumentViewerBase.DocumentProperty, "Document ", "DataContextChanged"); ConventionManager.AddElementConvention <PasswordBox>(ContentElementBinder.PasswordProperty, "Password", "PasswordChanged") .ApplyBinding = (viewModelType, path, property, element, convention) => { //по умолчанию для PasswordBox установлен шрифт times new roman //высота поля ввода вычисляется на основе шрифта //если расположить TextBox и PasswordBox на одном уровне то разница в высоте будет заметна //правим эту кривизну ((PasswordBox)element).FontFamily = SystemFonts.MessageFontFamily; return(ConventionManager.SetBindingWithoutBindingOverwrite(viewModelType, path, property, element, convention, convention.GetBindableProperty(element))); }; ConventionManager.AddElementConvention <MultiSelector>(ItemsControl.ItemsSourceProperty, "SelectedItem", "SelectionChanged") .ApplyBinding = (viewModelType, path, property, element, convention) => TryBindSelectedItems(viewModelType, path, property, element, convention, ((MultiSelector)element).SelectedItems); ConventionManager.AddElementConvention <ListBox>(ItemsControl.ItemsSourceProperty, "SelectedItem", "SelectionChanged") .ApplyBinding = (viewModelType, path, property, element, convention) => TryBindSelectedItems(viewModelType, path, property, element, convention, ((ListBox)element).SelectedItems); ConventionManager.AddElementConvention <ComboBox>(ItemsControl.ItemsSourceProperty, "SelectedItem", "SelectionChanged") .ApplyBinding = (viewModelType, path, property, element, convention) => { NotifyValueSupport.Patch(ref path, ref property); if (property.PropertyType.IsEnum) { if (NotBindedAndNull(element, ItemsControl.ItemsSourceProperty) && !ConventionManager.HasBinding(element, Selector.SelectedItemProperty)) { var items = DescriptionHelper.GetDescriptions(property.PropertyType); element.SetValue(ItemsControl.DisplayMemberPathProperty, "Name"); element.SetValue(ItemsControl.ItemsSourceProperty, items); var binding = new Binding(path); binding.Converter = new ComboBoxSelectedItemConverter(); binding.ConverterParameter = items; BindingOperations.SetBinding(element, Selector.SelectedItemProperty, binding); } } else { var fallback = ConventionManager.GetElementConvention(typeof(Selector)); if (fallback != null) { return(fallback.ApplyBinding(viewModelType, path, property, element, fallback)); } } return(true); }; ConventionManager.AddElementConvention <DataGrid>(ItemsControl.ItemsSourceProperty, "SelectedItem", "SelectionChanged") .ApplyBinding = (viewModelType, path, property, element, convention) => { var dataGrid = (DataGrid)element; if (dataGrid.Columns.Count > 1) { Interaction.GetBehaviors(element).Add(new CustomMenu()); } var fallback = ConventionManager.GetElementConvention(typeof(MultiSelector)); if (fallback != null) { var actualProperty = property; var result = fallback.ApplyBinding(viewModelType, path, actualProperty, element, fallback); var dummy = ""; NotifyValueSupport.Patch(ref dummy, ref actualProperty); var propertyType = actualProperty.PropertyType; if (result && propertyType.IsGenericType && typeof(IEnumerable).IsAssignableFrom(propertyType)) { ConfigureDataGrid(dataGrid, propertyType.GetGenericArguments()[0]); } return(result); } return(false); }; ConventionManager.AddElementConvention <Label>(ContentControl.ContentProperty, "Content", "DataContextChanged") .ApplyBinding = (viewModelType, path, property, element, convention) => { return(ConventionManager.SetBindingWithoutBindingOverwrite(viewModelType, path, property, element, convention, convention.GetBindableProperty(element))); }; }