Tell me how the table cell alignment magic happens

5 posts, 1 answers
  1. Will
    Will avatar
    11 posts
    Member since:
    Apr 2012

    Posted 22 Aug 2012 Link to this post

    I've got a RRTB with the RRTBRUI in my application, where table cell alignment is all botched.

    (The ribbon was created by dropping the RRTBRUI on the design surface.  I then removed editing options I don't want the user to have.)

    To illustrate, please view the attached image.  You can see that not only is 1) the context menu alignment button 2) not being respected within the design surface, but also 3) within the ribbon you can click an entire row of alignment buttons.

    To try and debug this, I have
    • copied the exact markup into a minimal solution
    • compared mouse events
    • examined application resources
    • cranked wpf trace levels to ALL
    • Listened to RTB command events

    Copied the markup exactly, and was unable to repro in a minimal solution.  Damn.

    I watched mouse events in both a working example and in my non-working example, and did not see events being handled any differently.  Damn.

    I checked to see if there were any Styles with default keys that were interfering with the RadToggleButton in any way, and had none.  Damn.

    Cranked up all trace levels and repro'd.  Nothing.  Well, actually LOTS of nothing.  But 99% was binding failures before the commands binding was updated ("DataItem=null"), and the rest were about "Path=Menu.IconColumnWidth".  Damn.

    Listened to CommandError, CommandExecuting, and CommandExecuted.  Verified the correct command and the correct command parameters are being passed every time, for every button.  And CommandError never fires when using these buttons.  Damn.

    So that leaves me stumped.  I know the RRTBRUI is doing stuff in the background, probably walking its children, managing their state.  But I don't know how this is happening, so I can't figure out what is going wrong.

    How does the RRTBRUI handle cell alignment?  What are the things that could go wrong?  Any ideas?
  2. Martin Ivanov
    Admin
    Martin Ivanov avatar
    104 posts

    Posted 27 Aug 2012 Link to this post

    Hello Will,

    Thank you for your feedback. However, we haven't encountered such an issue before and unfortunately without any steps to reproduce the problem, we cannot comment on it.

    Can you please send us a cut of your solution where the problem persists so that we can help you? If you open a support ticket and attach your solution, it will not be used for any other purpose than investigating the case.

    Thank you for your understanding.

    All the best,
    Martin
    the Telerik team

    Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

  3. UI for WPF is Visual Studio 2017 Ready
  4. Will
    Will avatar
    11 posts
    Member since:
    Apr 2012

    Posted 27 Aug 2012 Link to this post

    Unfortunately, I'd have to spend a decent amount of time cutting it out.  As in, it is less costly to throw cell positioning away rather than attempt to isolate the issue.

    Can I just get the algorithm for how the ribbon UI manages these buttons?  What methods it calls, what is it listening for, how is this done?  
    If you're using DependencyPropertyDescriptor to add a watch to a DP, and if you don't keep a reference to the DPD you are using to add the watch

    //this is pseudocode; doing it from memory
    var foo = DependencyPropertyDescriptor.FromProperty(lah, dedah);
    foo.AddValueChanged(someObject, someMethod);
    // foo goes out of scope here

    then I think I know what's happening, and it isn't anything you guys are doing.  Well, other than the fact that DPDs can become detached, discarded and collected without you ever knowing.  This can happen in some rare cases, such as within a wf4 designer (my situation).

    So, if this is part of the ribbon "magic", then I know what the problem is, what feature request to submit to you guys, and what my solution is (none, for now).  If you're doing something else, then I can investigate other avenues.
  5. Answer
    Martin Ivanov
    Admin
    Martin Ivanov avatar
    104 posts

    Posted 29 Aug 2012 Link to this post

    Hi Will,

    Assuming you have auto generated RadRichTextBoxRibbonUI or you have copied the code from the demos, the buttons will be wired using the RichTextCommand attached property specified:

    public static readonly DependencyProperty RichTextCommandProperty =
               DependencyProperty.RegisterAttached(
               "RichTextCommand",
               typeof(RichTextBoxCommandBase),
               typeof(RadRichTextBoxRibbonUI),
               new System.Windows.PropertyMetadata(new PropertyChangedCallback(OnRichTextBoxCommandChanged)));

    and it's callback:

    private static void OnRichTextBoxCommandChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
            {
               ...
     
                else if (o is RadRibbonToggleButton && (e.NewValue is ChangeTextAlignmentCommand || e.OldValue is ChangeTextAlignmentCommand))
                {
                    AttachChangeTextAlignmentCommand(
                        o as RadRibbonToggleButton,
                        e.OldValue as ChangeTextAlignmentCommand,
                        e.NewValue as ChangeTextAlignmentCommand);
                }
             ...
             if (e.OldValue != null && e.NewValue == null)
                {
                    ClearAttachedProperties(o);
                }
            }

    and here is how the command is attached to the button:

    private static void AttachChangeTextAlignmentCommand(
            RadRibbonToggleButton radRibbonToggleButton,
            ChangeTextAlignmentCommand oldCommand,
            ChangeTextAlignmentCommand newCommand)
        {
            radRibbonToggleButton.Command = newCommand;
     
            if (oldCommand != null)
            {
                EventHandler<StylePropertyChangedEventArgs<RadTextAlignment?>> oldHandler =
                    GetToggleHandlerButton<RadTextAlignment?>(radRibbonToggleButton);
     
                if (oldHandler != null)
                {
                    oldCommand.TextAlignmentChanged -= oldHandler;
                }
            }
     
            if (newCommand != null)
            {
                EventHandler<StylePropertyChangedEventArgs<RadTextAlignment?>> newHandler =
                    new EventHandler<StylePropertyChangedEventArgs<RadTextAlignment?>>((s, e) =>
                    {
                        bool isChecked = false;
     
                        RadTextAlignment commandAlignment;
                        if (ChangeTextAlignmentCommand.TryConvertCommandParameter(radRibbonToggleButton.CommandParameter, out commandAlignment))
                        {
                            isChecked = e.NewValue == commandAlignment;
                        }
                        else
                        {
                            isChecked = false;
                        }
     
                        radRibbonToggleButton.IsChecked = isChecked;
                    });
     
                newHandler.Invoke(newCommand, newCommand.GetEventArgs());
     
                RadRichTextBoxRibbonUI.SetCommandStateChangedHandler(radRibbonToggleButton, newHandler);
                newCommand.TextAlignmentChanged += newHandler;
            }
        }

    where 

    private static void SetCommandStateChangedHandler(DependencyObject obj, object value)
          {
              obj.SetValue(CommandStateChangedHandlerProperty, value);
          }
     
          private static readonly DependencyProperty CommandStateChangedHandlerProperty =
              DependencyProperty.RegisterAttached("CommandStateChangedHandler", typeof(object), typeof(RadRichTextBoxRibbonUI), null);

    You can download the source of all controls from your account and further investigate what the command does.

    We hope this helps. Don't hesitate to contact us if you have other questions or comments.


    Greetings,
    Martin
    the Telerik team

    Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

  6. Will
    Will avatar
    11 posts
    Member since:
    Apr 2012

    Posted 29 Aug 2012 Link to this post

    Thanks for that info.  Now I'll have something to go off of when we move the resolution for this out of the backlog.
Back to Top
UI for WPF is Visual Studio 2017 Ready