public void ProcessPath(IServiceProvider serviceProvider) { if (string.IsNullOrWhiteSpace(_path)) { _binding = new Binding(); return; } var parts = _path.Split('.').Select(o => o.Trim()).ToArray(); RelativeSource relativeSource = null; string elementName = null; var partIndex = 0; // 格式:{BindTo #MyTextBox.Text} if (parts[0].StartsWith("#")) { // 获取对象名 elementName = parts[0].Substring(1); partIndex++; } // 格式:{BindTo Ancestor.typeOfAncestor.PathToProperty} else if ("ancestors" == parts[0].ToLower() || "ancestor" == parts[0].ToLower()) { if (2 > parts.Length) { throw new Exception("Invalid path, expected exactly 2 identifiers ancestors.#Type#.[Path] (e.g. Ancestors.DataGrid, Ancestors.DataGrid.SelectedItem, Ancestors.DataGrid.SelectedItem.Text)"); } var typeName = parts[1]; var type = (Type) new TypeExtension(typeName).ProvideValue(serviceProvider); if (null == type) { throw new Exception($"Could not find type: {typeName}"); } relativeSource = new RelativeSource(RelativeSourceMode.FindAncestor, type, 1); partIndex += 2; } // 格式:{BindTo Template.PathToProperty} else if ("template" == parts[0].ToLower() || "templateparent" == parts[0].ToLower() || "templated" == parts[0].ToLower() || "templatedparent" == parts[0].ToLower()) { relativeSource = new RelativeSource(RelativeSourceMode.TemplatedParent); partIndex++; } // 格式:{BindTo ThisWindow} else if ("thiswindow" == parts[0].ToLower()) { relativeSource = new RelativeSource(RelativeSourceMode.FindAncestor, typeof(Window), 1); partIndex++; } // 格式:{BindTo This} else if ("this" == parts[0].ToLower()) { relativeSource = new RelativeSource(RelativeSourceMode.Self); partIndex++; } var parts4Path = parts.Skip(partIndex); IValueConverter valueConverter = null; if (parts4Path.Any()) { var sLastPart4Path = parts4Path.Last(); if (sLastPart4Path.EndsWith("()")) { parts4Path = parts4Path.Take(parts4Path.Count() - 1); _methodName = sLastPart4Path.Remove(sLastPart4Path.Length - 2); valueConverter = new CallMethodValueConverter(_methodName); } } var path = string.Join(".", parts4Path.ToArray()); if (string.IsNullOrWhiteSpace(path)) { _binding = new Binding(); } else { _binding = new Binding(path); } if (null != elementName) { _binding.ElementName = elementName; } if (null != relativeSource) { _binding.RelativeSource = relativeSource; } if (null != valueConverter) { _binding.Converter = valueConverter; } }
public void ProcessPath(IServiceProvider serviceProvider) { if (string.IsNullOrWhiteSpace(_Path)) { _Binding = new Binding(); return; } var Parts = _Path.Split('.').Select(o => o.Trim()).ToArray(); RelativeSource oRelativeSource = null; string sElementName = null; var PartIndex = 0; if (Parts[0].StartsWith("#")) { sElementName = Parts[0].Substring(1); PartIndex++; } else if (Parts[0].ToLower() == "ancestors" || Parts[0].ToLower() == "ancestor") { if (Parts.Length < 2) { throw new Exception("Invalid path, expected exactly 2 identifiers ancestors.#Type#.[Path] (e.g. Ancestors.DataGrid, Ancestors.DataGrid.SelectedItem, Ancestors.DataGrid.SelectedItem.Text)"); } var sType = Parts[1]; var oType = (Type) new System.Windows.Markup.TypeExtension(sType).ProvideValue(serviceProvider); if (oType == null) { throw new Exception("Could not find type: " + sType); } oRelativeSource = new RelativeSource(RelativeSourceMode.FindAncestor, oType, 1); PartIndex += 2; } else if (Parts[0].ToLower() == "template" || Parts[0].ToLower() == "templateparent" || Parts[0].ToLower() == "templatedparent" || Parts[0].ToLower() == "templated") { oRelativeSource = new RelativeSource(RelativeSourceMode.TemplatedParent); PartIndex++; } else if (Parts[0].ToLower() == "thiswindow") { oRelativeSource = new RelativeSource(RelativeSourceMode.FindAncestor, typeof(Window), 1); PartIndex++; } else if (Parts[0].ToLower() == "this") { oRelativeSource = new RelativeSource(RelativeSourceMode.Self); PartIndex++; } var PartsForPathString = Parts.Skip(PartIndex); IValueConverter ValueConverter = null; if (PartsForPathString.Any()) { var sLastPartForPathString = PartsForPathString.Last(); if (sLastPartForPathString.EndsWith("()")) { PartsForPathString = PartsForPathString.Take(PartsForPathString.Count() - 1); _MethodName = sLastPartForPathString.Remove(sLastPartForPathString.Length - 2); ValueConverter = new CallMethodValueConverter(_MethodName); } } var Path = string.Join(".", PartsForPathString.ToArray()); if (string.IsNullOrWhiteSpace(Path)) { _Binding = new Binding(); } else { _Binding = new Binding(Path); } if (sElementName != null) { _Binding.ElementName = sElementName; } if (oRelativeSource != null) { _Binding.RelativeSource = oRelativeSource; } if (ValueConverter != null) { _Binding.Converter = ValueConverter; } }
private bool ProcessPath(IServiceProvider serviceProvider) { //////////////////////////////////////////////////////////////////////////////// // Validation. //////////////////////////////////////////////////////////////////////////////// if (string.IsNullOrWhiteSpace(this.path)) { binding = new Binding(); return(true); } //////////////////////////////////////////////////////////////////////////////// // Variables. //////////////////////////////////////////////////////////////////////////////// var parts = this.path.Split('.').Select(o => o.Trim()).ToArray(); var partIndex = 0; RelativeSource oRelativeSource = null; Object oSource = null; string elementName = null; //////////////////////////////////////////////////////////////////////////////// // Determine and process the 'entry' binding type. //////////////////////////////////////////////////////////////////////////////// if (parts[0].StartsWith("#")) { elementName = parts[0].Substring(1); partIndex++; } else if (parts[0].ToLower() == "ancestors" || parts[0].ToLower() == "ancestor") { if (parts.Length < 2) { throw new Exception("Invalid path, expected exactly 2 identifiers ancestors.#Type#.[Path] (e.g. Ancestors.DataGrid, Ancestors.DataGrid.SelectedItem, Ancestors.DataGrid.SelectedItem.Text)"); } var sType = parts[1]; var oType = (Type) new System.Windows.Markup.TypeExtension(sType).ProvideValue(serviceProvider); if (oType == null) { throw new Exception("Could not find type: " + sType); } oRelativeSource = new RelativeSource(RelativeSourceMode.FindAncestor, oType, 1); partIndex += 2; } else if (parts[0].ToLower() == "template" || parts[0].ToLower() == "templateparent" || parts[0].ToLower() == "templatedparent" || parts[0].ToLower() == "templated") { oRelativeSource = new RelativeSource(RelativeSourceMode.TemplatedParent); partIndex++; } else if (parts[0].ToLower() == "thiswindow" || parts[0].ToLower() == "window") { oRelativeSource = new RelativeSource(RelativeSourceMode.FindAncestor, typeof(Window), 1); partIndex++; } else if (parts[0].ToLower() == "root") { IRootObjectProvider rootProvider = serviceProvider.GetService(typeof(IRootObjectProvider)) as IRootObjectProvider; oSource = (rootProvider != null) ? rootProvider.RootObject : null; partIndex++; } else if (parts[0].ToLower() == "this") { oRelativeSource = new RelativeSource(RelativeSourceMode.Self); partIndex++; } //////////////////////////////////////////////////////////////////////////////// // Advanced path. //////////////////////////////////////////////////////////////////////////////// var partsForPathString = parts.Skip(partIndex); IValueConverter callMethodConverter = null; //////////////////////////////////////////////////////////////////////////////// // Special processing for binding to Methods and Commands. //////////////////////////////////////////////////////////////////////////////// if (partsForPathString.Any()) { var sLastPartForPathString = partsForPathString.Last(); if (sLastPartForPathString.EndsWith("()")) { // Retrieve target info. IProvideValueTarget provideValueTarget = serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget; DependencyObject targetObject = null; object targetProperty = null; if (provideValueTarget != null) { targetObject = provideValueTarget.TargetObject as DependencyObject; targetProperty = provideValueTarget.TargetProperty; } if (targetProperty != null && targetProperty is DependencyProperty) { partsForPathString = partsForPathString.Take(partsForPathString.Count() - 1); methodName = sLastPartForPathString.Remove(sLastPartForPathString.Length - 2); callMethodConverter = new CallMethodValueConverter(methodName); } else if (targetProperty != null && targetProperty.GetType().FullName.Equals("System.Reflection.RuntimeEventInfo")) // else if (targetProperty != null && targetProperty is System.Reflection.RuntimeEventInfo) // RuntimeEventInfo is locked away where I cant even compare against the type directly. { InternalBindToMethod(oSource, sLastPartForPathString, targetObject, targetProperty); // Return false indicating Parsing is done and we don't want to do any actual XAML binding. // We've already bound the proxy directly to the event object. return(false); } } } //////////////////////////////////////////////////////////////////////////////// // Compute the 'Path' //////////////////////////////////////////////////////////////////////////////// var bindingPath = string.Join(".", partsForPathString.ToArray()); //////////////////////////////////////////////////////////////////////////////// // Build the Binding element. //////////////////////////////////////////////////////////////////////////////// if (string.IsNullOrWhiteSpace(bindingPath)) { binding = new Binding(); } else { binding = new Binding(bindingPath); } if (elementName != null) { binding.ElementName = elementName; } if (oRelativeSource != null) { binding.RelativeSource = oRelativeSource; } if (oSource != null) { binding.Source = oSource; } if (callMethodConverter != null) { binding.Converter = callMethodConverter; } else if (this.converter != null) { binding.Converter = this.converter; } //////////////////////////////////////////////////////////////////////////////// // Build - Propagate Properties. // - It turns out that property propagation validation is problematic. We were trying to // determine if the user was trying to overwrite a property that previous processing has // already explicitly set. In this situation we wanted to throw error/exception. // - However, this is a problem in that several of Binding's properties are of value type and/or // get default values, so it is non trivial to determine if the above processing has set the value // or if it is just a default value; add to this that that default value can be different // based on which XAML property type is being bound to. // - So to make this work completely, we'd have to depend solely on the processing the above // does; i.e. keep track of which binding properties the processing does. //////////////////////////////////////////////////////////////////////////////// ValidatePropagateProperty(binding.AsyncState, AsyncState); // ValidatePropagateProperty(binding.BindsDirectlyToSource , BindsDirectlyToSource); ValidatePropagateProperty(binding.ConverterCulture, ConverterCulture); ValidatePropagateProperty(binding.ConverterParameter, ConverterParameter); ValidatePropagateProperty(binding.ElementName, ElementName); // ValidatePropagateProperty(binding.IsAsync , IsAsync); // ValidatePropagateProperty(binding.Mode , Mode); // ValidatePropagateProperty(binding.NotifyOnSourceUpdated , NotifyOnSourceUpdated); // ValidatePropagateProperty(binding.NotifyOnTargetUpdated , NotifyOnTargetUpdated); // ValidatePropagateProperty(binding.NotifyOnValidationError , NotifyOnValidationError); //ValidatePropagateProperty(binding.RelativeSource , RelativeSource); //ValidatePropagateProperty(binding.Source , Source); //ValidatePropagateProperty(binding.Path , Path); ValidatePropagateProperty(binding.UpdateSourceExceptionFilter, UpdateSourceExceptionFilter); // ValidatePropagateProperty(binding.UpdateSourceTrigger , UpdateSourceTrigger); // ValidatePropagateProperty(binding.ValidatesOnDataErrors , ValidatesOnDataErrors); // ValidatePropagateProperty(binding.ValidatesOnExceptions , ValidatesOnExceptions); // ValidatePropagateProperty(binding.ValidatesOnNotifyDataErrors , ValidatesOnNotifyDataErrors); //ValidatePropagateProperty(binding.ValidationRules { get); } , ValidationRules { get); } ValidatePropagateProperty(binding.XPath, XPath); if (AsyncState.HasValue()) { binding.AsyncState = AsyncState; } if (BindsDirectlyToSource.HasValue) { binding.BindsDirectlyToSource = BindsDirectlyToSource.Value; } if (ConverterCulture.HasValue()) { binding.ConverterCulture = ConverterCulture; } if (ConverterParameter.HasValue()) { binding.ConverterParameter = ConverterParameter; } if (ElementName.HasValue()) { binding.ElementName = ElementName; } if (IsAsync.HasValue) { binding.IsAsync = IsAsync.Value; } if (Mode.HasValue) { binding.Mode = Mode.Value; } if (NotifyOnSourceUpdated.HasValue) { binding.NotifyOnSourceUpdated = NotifyOnSourceUpdated.Value; } if (NotifyOnTargetUpdated.HasValue) { binding.NotifyOnTargetUpdated = NotifyOnTargetUpdated.Value; } if (NotifyOnValidationError.HasValue) { binding.NotifyOnValidationError = NotifyOnValidationError.Value; } //binding.RelativeSource = RelativeSource; //binding.Source = Source; //binding.Path = Path; if (UpdateSourceExceptionFilter.HasValue()) { binding.UpdateSourceExceptionFilter = UpdateSourceExceptionFilter; } if (UpdateSourceTrigger.HasValue) { binding.UpdateSourceTrigger = UpdateSourceTrigger.Value; } if (ValidatesOnDataErrors.HasValue) { binding.ValidatesOnDataErrors = ValidatesOnDataErrors.Value; } if (ValidatesOnExceptions.HasValue) { binding.ValidatesOnExceptions = ValidatesOnExceptions.Value; } if (ValidatesOnNotifyDataErrors.HasValue) { binding.ValidatesOnNotifyDataErrors = ValidatesOnNotifyDataErrors.Value; } if (Delay.HasValue) { binding.Delay = Delay.Value; } //binding.ValidationRules = ValidationRules { get; } if (XPath.HasValue()) { binding.XPath = XPath; } //////////////////////////////////////////////////////////////////////////////// // Binding property set successfully. //////////////////////////////////////////////////////////////////////////////// return(true); }
public void ProcessPath(IServiceProvider serviceProvider) { if (string.IsNullOrWhiteSpace(_Path)) { _Binding = new Binding(); return; } var Parts = _Path.Split('.').Select(o => o.Trim()).ToArray(); RelativeSource oRelativeSource = null; string sElementName = null; var PartIndex = 0; if (Parts[0].StartsWith("#")) { sElementName = Parts[0].Substring(1); PartIndex++; } else if (Parts[0].ToLower() == "ancestors" || Parts[0].ToLower() == "ancestor") { if (Parts.Length < 2) throw new Exception("Invalid path, expected exactly 2 identifiers ancestors.#Type#.[Path] (e.g. Ancestors.DataGrid, Ancestors.DataGrid.SelectedItem, Ancestors.DataGrid.SelectedItem.Text)"); var sType = Parts[1]; var oType = (Type)new System.Windows.Markup.TypeExtension(sType).ProvideValue(serviceProvider); if (oType == null) throw new Exception("Could not find type: " + sType); oRelativeSource = new RelativeSource(RelativeSourceMode.FindAncestor, oType, 1); PartIndex += 2; } else if (Parts[0].ToLower() == "template" || Parts[0].ToLower() == "templateparent" || Parts[0].ToLower() == "templatedparent" || Parts[0].ToLower() == "templated") { oRelativeSource = new RelativeSource(RelativeSourceMode.TemplatedParent); PartIndex++; } else if (Parts[0].ToLower() == "thiswindow") { oRelativeSource = new RelativeSource(RelativeSourceMode.FindAncestor, typeof(Window), 1); PartIndex++; } else if (Parts[0].ToLower() == "this") { oRelativeSource = new RelativeSource(RelativeSourceMode.Self); PartIndex++; } var PartsForPathString = Parts.Skip(PartIndex); IValueConverter ValueConverter = null; if (PartsForPathString.Any()) { var sLastPartForPathString = PartsForPathString.Last(); if (sLastPartForPathString.EndsWith("()")) { PartsForPathString = PartsForPathString.Take(PartsForPathString.Count() - 1); _MethodName = sLastPartForPathString.Remove(sLastPartForPathString.Length - 2); ValueConverter = new CallMethodValueConverter(_MethodName); } } var Path = string.Join(".", PartsForPathString.ToArray()); if (string.IsNullOrWhiteSpace(Path)) { _Binding = new Binding(); } else { _Binding = new Binding(Path); } if (sElementName != null) { _Binding.ElementName = sElementName; } if (oRelativeSource != null) { _Binding.RelativeSource = oRelativeSource; } if (ValueConverter != null) { _Binding.Converter = ValueConverter; } }