0

Using WPF: A Simple Color Picker With Preview, Sacha Barber, 18 Apr 2012 , I created a custom control from it:

public class ColorCustomControl : Control 
{....}

It is then used as:

<Menu....>
    <MenuItem.....>
       <pn:ColorCustomControl/>
    </MenuItem>
</Menu>

This yields the following picture when the Brushes MenuItem is selected:

enter image description here

Selection of any item in the opened Brushes submenu results in the appropriate action being taken with the Brushes submenu REMAINING OPEN. This is the effect I want.

However, as shown below, selection of any of the three swatches results in a quick flicker of the new swatch -- it replaces the color pattern to the left of "Preview"--followed immediately by closure of the Brushes submenu.

If the Brushes menuitem is again chosen, the most recently selected swatch correctly appears.

I have tried all preview events (i.e., keyboard lost focus, left mouse down, etc.), to try stopping closure of the submenu when a swatch is chosen. Nothing I have found will stop the popup from closing.

How can closure of the Brushes submenu be prevented when selecting a swatch from the visual?

(I strongly suspect that redrawing of the visual, as in InvalidateVisual() when a new swatch image is selected, is forcing closure of the submenu).

Any ideas anybody?

TIA

Alan Wayne
  • 5,122
  • 10
  • 52
  • 95
  • I have found [this SO answer](https://stackoverflow.com/a/5260880/2029607) which is using `StaysOpenOnClick` have you tried this? – XAMlMAX Oct 17 '17 at 10:11
  • @XAMlMAX Yes...It does not work, nor does overriding PreviewLostKeyboardFocus or any method use of IsSubmenuOpen. Nothing seems to work to keep this open after a redraw of the chosen swatch,even though selection of any other of the menu items does not close the popup. Since this is the only selection that forces a redraw, I suspect that InvalidateVisual() is forcing closure of the popup. Don't know for sure--nor how to reopen the popup programmatically after its untimely closure. – Alan Wayne Oct 17 '17 at 12:41

1 Answers1

1

My suggestion is to stop events propagation from your user control. So in your ColorCustomControl class first of all add a property (it can be a dependency one too if you need):

private bool propagateEvents = true;

public bool PropagateEvents
{
    get
    {
        return propagateEvents;
    }
    set
    {
        propagateEvents = value;
    }
}

Then add e.Handled = !PropagateEvents; at the end of every mouse event handler; in the end add a Swatch_MouseLeftButtonUp method (it has to handle the event raised by ImgSqaure1, ImgSqaure2 and ImgCircle1). The result will be:

private void Swatch_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    Image img = (sender as Image);
    ColorImage.Source = img.Source;

    e.Handled = !PropagateEvents;
}

private void Swatch_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
    e.Handled = !PropagateEvents;
}

private void CanvImage_MouseDown(object sender, MouseButtonEventArgs e)
{
    IsMouseDown = true;
    e.Handled = !PropagateEvents;
}

private void CanvImage_MouseUp(object sender, MouseButtonEventArgs e)
{
    IsMouseDown = false;
    e.Handled = !PropagateEvents;
}

and in the user control XAML:

<Image x:Name="ImgSqaure1" 
        Height="20" Width="20" 
        Source="Images/ColorSwatchSquare1.png" 
        Margin="45,0,0,0" 
        ToolTip="Square swatch1" 
        MouseLeftButtonDown="Swatch_MouseLeftButtonDown"
        MouseLeftButtonUp="Swatch_MouseLeftButtonUp"/>
<Image x:Name="ImgSqaure2" 
        Height="20" Width="20" 
        Source="Images/ColorSwatchSquare2.png" Margin="5,0,0,0" 
        ToolTip="Square swatch2" 
        MouseLeftButtonDown="Swatch_MouseLeftButtonDown"
        MouseLeftButtonUp="Swatch_MouseLeftButtonUp"/>
<Image x:Name="ImgCircle1" Height="20" Width="20" 
        Source="Images/ColorSwatchCircle.png" Margin="5,0,0,0" 
        ToolTip="Circle swatch1" 
        MouseLeftButtonDown="Swatch_MouseLeftButtonDown"
        MouseLeftButtonUp="Swatch_MouseLeftButtonUp" />

Now all you have to do is set the PropagateEvents property in your menu:

<Menu....>
    <MenuItem.....>
       <pn:ColorCustomControl PropagateEvents="False" />
    </MenuItem>
</Menu>

I hope it can help you.

Il Vic
  • 5,576
  • 4
  • 26
  • 37
  • Thank you. That worked! I had tried this earlier, but I only marked the MouseLeftButtonDown event -- not both the Down AND Up events. This fails if ONLY the MouseLeftButtonDown event is marked as handled. Marking both Down and Up events as handled on the Swatch did the trick:) – Alan Wayne Oct 17 '17 at 18:50