locked
How do I bind to a control? RRS feed

  • Question

  • In SL 4, I had this:

       <guardianControls:EnhancedBusyIndicator IsBusy="{Binding IsBusy}" BusyContent="{Binding BusyMessage}" Margin="0,-4,0,4" x:Name="BusyIndicator"       

    ControlToFocusOn="{Binding FocusControl, ElementName=GeneralInfoView1}"                            

    Where FocusControl was a readonly property of the GeneralInfoView1 and of type Control. 

    But now I get an error that says:

    "Object of type 'System.Windows.Data.BindingExpression' cannot be

    converted to type 'System.Windows.Control.Control'"

    Can anybody give me a clue what the message is trying to tell me and why I can't bind to a Control so that my EnhancedBusyIndicator can get addressability to that control?



    • Edited by Mark Tiede Thursday, July 9, 2015 8:18 PM
    Thursday, July 9, 2015 8:16 PM

All replies

  • Hi Mark,

    Based on your code and description, I try with custom control's property bind to custom control and custom control's property bind to control which get from Toolbox. The latter is works fine. But the former give me a error message which is fimilar with yours "Object of type 'System.Windows.Data.Binding' cannot be converted to type 'System.String'".

    But when I modify the MyText property as  DependencyProperty, it works fine. Please check if the ControlToFocusOn is  DependencyProperty.


    Best Regards,
    Weiwei

    Friday, July 10, 2015 9:59 AM
    Moderator
  • Since my first post implied that it all worked fine in SL 4, then it must have already been a dependency property.  And it is in SL 5 too, since nothing was changed in the code.

    Friday, July 10, 2015 12:01 PM
  • Despite getting that error message at design time, at runtime, the ControlToFocusOn DOES have a control in it and it appears to be the right one.

    So how do I get rid of the design time warning?

    We had another where:

    <Image Source="{StaticResource EO_PlusImage}"/>

    complained when EO_PlusImage was a string.

    We had to change that to:

    <Image Source="{Binding Source={StaticResource EO_PlusImage}}"/>
    

    So is there some similar syntax change that would make the designer happy?

    • Edited by Mark Tiede Saturday, July 11, 2015 12:33 PM
    Friday, July 10, 2015 9:12 PM
  • Hi Mark,

    Please try modify your code as below.

    ControlToFocusOn="{Binding Path=FocusControl, ElementName=GeneralInfoView1}"

    Best Regards,
    Weiwei

    Monday, July 13, 2015 6:41 AM
    Moderator
  • I THINK I got it. I had declared my dependency property inappropriately. Apparently, in SL 4, it managed to work anyway, but in SL 5, it was complaining in the designer, but still working.

    I had declared the dependency property as readonly, but NOT as PUBLIC, and I was initializing them in the constructor.  I'm surprised it worked at all and glad the error message was output on SL 5.

    FYI, here is the original and the fixed code (in RemObject's Oxygene language):

    namespace Guardian.EditObservation.Controls;
    
    interface
    
       uses
          System.Collections.Generic,
          System.Text, 
          System.Windows,
          System.Windows.Controls;
    
    
       type
          EnhancedBusyIndicator = public class(BusyIndicator)
             protected
                method OnIsBusyChanged( e: DependencyPropertyChangedEventArgs ); override;
             private
                AllowedToFocusProperty: DependencyProperty ; readonly;
                method GetAllowedToFocus: Boolean;
                method SetAllowedToFocus( value: Boolean );
    
             private
                ControlToFocusOnProperty: DependencyProperty; readonly;
                method GetControlToFocusOn: Control;
                method SetControlToFocusOn( value: Control );
    
             private
                method EnhancedBusyIndicator_Loaded( sender: Object; e: RoutedEventArgs );
    
             public
                constructor ;
                property AllowedToFocus   : Boolean read GetAllowedToFocus   write SetAllowedToFocus;
                property ControlToFocusOn : Control read GetControlToFocusOn write SetControlToFocusOn;
    
             end;
    
    
    implementation
    
    
       constructor EnhancedBusyIndicator;
          begin
          AllowedToFocusProperty   := DependencyProperty.Register( 'AllowedToFocus',   typeof( Boolean ), typeof( EnhancedBusyIndicator ), new PropertyMetadata( true ) );
          ControlToFocusOnProperty := DependencyProperty.Register( 'ControlToFocusOn', typeof( Control ), typeof( EnhancedBusyIndicator ), nil);
    
          Loaded += EnhancedBusyIndicator_Loaded;
          end;
    
       method EnhancedBusyIndicator.EnhancedBusyIndicator_Loaded( sender: Object; e: RoutedEventArgs );
          begin
          AllowedToFocus := true;
          end;
    
       method EnhancedBusyIndicator.OnIsBusyChanged( e: DependencyPropertyChangedEventArgs );
          begin
          inherited OnIsBusyChanged(e);
        
          if AllowedToFocus               and 
             ( not IsBusy               ) and
             ( ControlToFocusOn <> nil  ) then begin
             Dispatcher.BeginInvoke(
                () -> begin
                   ControlToFocusOn.Focus;
                   end
                );
    
             AllowedToFocus := false;
             end;
          end;
    
       method EnhancedBusyIndicator.GetAllowedToFocus: Boolean;
          begin
          result := Boolean( GetValue( AllowedToFocusProperty ) );
          end;
    
       method EnhancedBusyIndicator.SetAllowedToFocus( value: Boolean ); 
          begin
          SetValue( AllowedToFocusProperty, value );
          end;
    
       method EnhancedBusyIndicator.GetControlToFocusOn: Control;
          begin
          result := Control( GetValue( ControlToFocusOnProperty ) );
          end;
    
       method EnhancedBusyIndicator.SetControlToFocusOn( value: Control ); 
          begin
          SetValue( ControlToFocusOnProperty, value );
          end;
    
    end.

    And here is the corrected code:

    namespace Guardian.EditObservation.Controls;
    
    interface
    
       uses
          System.Collections.Generic,
          System.Text, 
          System.Windows,
          System.Windows.Controls;
    
    
       type
          EnhancedBusyIndicator = public class(BusyIndicator)
             protected
                method OnIsBusyChanged( e: DependencyPropertyChangedEventArgs ); override;
             public
                class AllowedToFocusProperty   : DependencyProperty; readonly;       <======= note changes
                class ControlToFocusOnProperty : DependencyProperty; readonly;       <======= note changes
    
             private
                method GetAllowedToFocus: Boolean;
                method SetAllowedToFocus( value: Boolean );
    
             private
                method GetControlToFocusOn: Control;
                method SetControlToFocusOn( value: Control );
    
             private
                method EnhancedBusyIndicator_Loaded( sender: Object; e: RoutedEventArgs );
    
             public
                class constructor;
                constructor ;
                property AllowedToFocus   : Boolean read GetAllowedToFocus   write SetAllowedToFocus;
                property ControlToFocusOn : Control read GetControlToFocusOn write SetControlToFocusOn; notify;
    
             end;
    
    
    implementation
    
       class constructor EnhancedBusyIndicator;   <==== note change
          begin
          AllowedToFocusProperty   := DependencyProperty.Register( 'AllowedToFocus',   typeof( Boolean ), typeof( EnhancedBusyIndicator ), new PropertyMetadata( true ) );
          ControlToFocusOnProperty := DependencyProperty.Register( 'ControlToFocusOn', typeof( Control ), typeof( EnhancedBusyIndicator ), nil);
          end;
    
       constructor EnhancedBusyIndicator;
          begin
                           <==== where lines were before
          Loaded += EnhancedBusyIndicator_Loaded;
          end;
    
       method EnhancedBusyIndicator.EnhancedBusyIndicator_Loaded( sender: Object; e: RoutedEventArgs );
          begin
          AllowedToFocus := true;
          end;
    
       method EnhancedBusyIndicator.OnIsBusyChanged( e: DependencyPropertyChangedEventArgs );
          begin
          inherited OnIsBusyChanged(e);
        
          if AllowedToFocus               and 
             ( not IsBusy               ) and
             ( ControlToFocusOn <> nil  ) then begin
             Dispatcher.BeginInvoke(
                () -> begin
                   ControlToFocusOn.Focus;
                   end
                );
    
             AllowedToFocus := false;
             end;
          end;
    
       method EnhancedBusyIndicator.GetAllowedToFocus: Boolean;
          begin
          result := Boolean( GetValue( AllowedToFocusProperty ) );
          end;
    
       method EnhancedBusyIndicator.SetAllowedToFocus( value: Boolean ); 
          begin
          SetValue( AllowedToFocusProperty, value );
          end;
    
       method EnhancedBusyIndicator.GetControlToFocusOn: Control;
          begin
          result := Control( GetValue( ControlToFocusOnProperty ) );
          end;
    
       method EnhancedBusyIndicator.SetControlToFocusOn( value: Control ); 
          begin
          SetValue( ControlToFocusOnProperty, value );
          end;
    
    
    end.



    • Edited by mltiede Monday, July 13, 2015 2:10 PM
    • Proposed as answer by mltiede Monday, July 13, 2015 2:10 PM
    Monday, July 13, 2015 2:08 PM