Esempio n. 1
0
        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);
            }
        }
Esempio n. 2
0
        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)));
            };
        }
Esempio n. 3
0
        public void Init(bool failfast)
        {
            MessageBus.Current.RegisterScheduler <string>(ImmediateScheduler.Instance, "db");

            ConventionManager.Singularize = s => {
                if (s == "Taxes")
                {
                    return("Tax");
                }
                if (s == "Value")
                {
                    return(s);
                }
                return(s.Singularize() ?? s);
            };
            //нужно затем что бы можно было делать модели без суффикса ViewModel
            //достаточно что бы они лежали в пространстве имен ViewModels
            ViewLocator.NameTransformer.AddRule(
                @"(?<nsbefore>([A-Za-z_]\w*\.)*)(?<subns>ViewModels\.)"
                + @"(?<nsafter>([A-Za-z_]\w*\.)*)(?<basename>[A-Za-z_]\w*)"
                + @"(?!<suffix>ViewModel)$",
                "${nsbefore}Views.${nsafter}${basename}View");
            //что бы не нужно было использовать суффиксы View и ViewModel
            ViewLocator.NameTransformer.AddRule(
                @"(?<nsbefore>([A-Za-z_]\w*\.)*)(?<subns>ViewModels\.)"
                + @"(?<nsafter>([A-Za-z_]\w*\.)*)(?<basename>[A-Za-z_]\w*)"
                + @"(?!<suffix>)$",
                "${nsbefore}Views.${nsafter}${basename}");

            //безумие - сам по себе Caliburn если не найден view покажет текст Cannot find view for
            //ни исключения ни ошибки в лог
            ViewLocator.LocateForModelType = (modelType, displayLocation, context) => {
                var viewType = ViewLocator.LocateTypeForModelType(modelType, displayLocation, context);
                if (viewType == null)
                {
                    if (failfast)
                    {
                        throw new Exception(String.Format("Не удалось найти вид для отображения {0}", modelType));
                    }
                    else
                    {
                        log.ErrorFormat("Не удалось найти вид для отображения {0}", modelType);
                    }
                }

                return(viewType == null
                                                        ? new TextBlock()
                                                        : ViewLocator.GetOrCreateViewType(viewType));
            };

            Conventions.Register();
            SaneCheckboxEditor.Register();
            NotifyValueSupport.Register();

            var customPropertyBinders = new Action <IEnumerable <FrameworkElement>, Type>[] {
                EnabledBinder.Bind,
                VisibilityBinder.Bind,
            };
            var customBinders = new Action <Type, IEnumerable <FrameworkElement>, List <FrameworkElement> >[] {
                //сначала должен обрабатываться поиск и только потом переход
                SearchBinder.Bind,
                NavBinder.Bind,
                EnterBinder.Bind,
            };

            var defaultBindProperties = ViewModelBinder.BindProperties;
            var defaultBindActions    = ViewModelBinder.BindActions;
            var defaultBind           = ViewModelBinder.Bind;

            ViewModelBinder.Bind = (viewModel, view, context) => {
                if ((bool)view.GetValue(ViewModelBinder.ConventionsAppliedProperty))
                {
                    return;
                }

                defaultBind(viewModel, view, context);
                ContentElementBinder.Bind(viewModel, view, context);
                Commands.Bind(viewModel, view, context);
                var baseScreen = viewModel as BaseScreen;
                //этот метод будет вызваться каждый раз при активации\деактивации формы
                //что бы избежать множественных подписок
                if (baseScreen != null && !baseScreen.ResultsSink.HasObservers)
                {
                    baseScreen.ResultsSink
                    .CatchSubscribe(r => Coroutine.BeginExecute(new List <IResult> {
                        r
                    }.GetEnumerator(), new ActionExecutionContext {
                        View = view
                    }), baseScreen.CloseCancellation);
                }
                var baseShell = viewModel as BaseShell;
                if (baseShell != null && !baseShell.ResultsSink.HasObservers)
                {
                    baseShell.ResultsSink
                    .CatchSubscribe(r => Coroutine.BeginExecute(new List <IResult> {
                        r
                    }.GetEnumerator(), new ActionExecutionContext {
                        View = view
                    }), baseShell.CancelDisposable);
                }
            };

            ViewModelBinder.BindProperties = (elements, type) => {
                foreach (var binder in customPropertyBinders)
                {
                    binder(elements, type);
                }
                return(defaultBindProperties(elements, type));
            };

            ViewModelBinder.BindActions = (elements, type) => {
                var binded = defaultBindActions(elements, type).ToList();

                foreach (var binder in customBinders)
                {
                    binder(type, elements, binded);
                }
                return(elements);
            };
        }