Greetings All,
I am getting some weird behavior from WPF when i create an event to programatically open a context menu. once I select a text and right click the highlight of the selection disappears once the context menu opens up.
Here is a sample of the problem:
Xaml:
<Window x:Class="WpfApplication19.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="287" Width="419">
<Grid>
<TextBox x:Name="myText" Height="38" Margin="0,72,6,0" VerticalAlignment="Top" HorizontalAlignment="Right" Width="135"></TextBox>
<Label Height="30" Margin="12,80,164,0" Name="label1" VerticalAlignment="Top">Textbox with contextMenu property set</Label>
<Label Height="30" Margin="12,0,136,91" Name="label2" VerticalAlignment="Bottom">TextBox Open ContextMenu by programmatically</Label>
<TextBox Height="38" Margin="0,0,6,81" x:Name="myText1" VerticalAlignment="Bottom" HorizontalAlignment="Right" Width="135" />
</Grid>
</Window>
And the Code Behind:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WpfApplication19
{
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class Window1 : Window
{
ContextMenu con = new ContextMenu();
public Window1()
{
InitializeComponent();
MenuItem menuItem1 = new MenuItem();
menuItem1.Header = "Menu1";
MenuItem menuItem2 = new MenuItem();
menuItem2.Header = "Menu2";
con.Items.Add(menuItem1);
con.Items.Add(menuItem2);
this.myText.ContextMenu = con;
this.myText1.PreviewMouseDown += new MouseButtonEventHandler(myText1_PreviewMouseDown);
}
void myText1_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
base.OnPreviewMouseDown(e);
if (e.RightButton == MouseButtonState.Pressed)
{
con.Placement = System.Windows.Controls.Primitives.PlacementMode.MousePoint;
con.IsOpen = true;
IInputElement focusedElement = FocusManager.GetFocusedElement(this);
}
}
}
}
Thank you in advance!
Note:
I found out that adding con.focusable = false tends to work with the solution. but can anybody explain why is that?
Whenever u open the contextmenu the focus will go to the contextmenu,
and that's why the textbox will hide the selection.
A Simple solution for this problem is:
Change contextmenu property Focusable to false
<ContextMenu Focusable="False">
And change Focusable for every item to false
<MenuItem Command="Copy" Focusable="False">
Simple example:
<TextBox Text="Right-click here for context menu!">
<TextBox.ContextMenu>
<ContextMenu Focusable="False">
<MenuItem Command="Cut" Focusable="False"/>
<MenuItem Command="Copy" Focusable="False"/>
<MenuItem Command="Paste" Focusable="False"/>
</ContextMenu>
</TextBox.ContextMenu>
</TextBox>
This way the focus will stay on the textbox,
and the highlight will remain Visible
I can get you started, but this solution has some serious usability issues that you may need to overcome.
Add a LostFocus event handler to control myText.
Set myText1.Focus() during the right-click event so that you can trigger the LostFocus event.
This solution means that myText stays selected when you might want to unselect its value.
Also take at look at this answer for more information.
<TextBox LostFocus="myText_LostFocus" x:Name="myText" Height="38" Margin="0,72,6,0" VerticalAlignment="Top" HorizontalAlignment="Right" Width="135"></TextBox>
void myText1_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
base.OnPreviewMouseDown(e);
if (e.RightButton == MouseButtonState.Pressed)
{
// added next line
myText1.Focus();
con.Placement = System.Windows.Controls.Primitives.PlacementMode.MousePoint;
con.IsOpen = true;
IInputElement focusedElement = FocusManager.GetFocusedElement(this);
}
}
private void myText_LostFocus(object sender, RoutedEventArgs e)
{
e.Handled = true;
}
Simply,
Properties > Hide Selection = False
Its nice to hear, you got the right answer. but simply this will also works
Thanks
Related
If you run the code neither of the list box items are selected. If you select either it remains selected okay and displays either "One" or "Two" in the text box accordingly. When the ResetListBox button is clicked the selected item is deselected (?maybe) but retains a grey background (undesired). Once the item has this light grey background the onClick event no longer fires... No additional text is added to the text box. This question has been asked in various forms all over the web and none of the answers that I've tried in this simple example has worked.
<Window x:Class="WpfApp1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp1"
mc:Ignorable="d"
Title="MainWindow" Height="279.186" Width="401.98">
<Grid Margin="0,0,-6.8,-2.4">
<ListBox x:Name="ThanklessListBox" HorizontalAlignment="Left" Height="89" Margin="24,25,0,0" VerticalAlignment="Top" Width="117">
<ListBoxItem x:Name="ItemI" Content="ItemUno" Selected="ItemI_Selected"/>
<ListBoxItem x:Name="Item2" Content="ItemDos" Selected="Item2_Selected"/>
</ListBox>
<TextBox x:Name="StuffToShow" HorizontalAlignment="Left" Height="178" Margin="198,25,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="116"/>
<Button x:Name="ResetListBox" Content="ResetListBox" HorizontalAlignment="Left" Height="26" Margin="28,131,0,0" VerticalAlignment="Top" Width="116" Click="ResetListBox_Click"/>
<Button x:Name="SeleectButton" Content="SelectItemDos" HorizontalAlignment="Left" Height="24" Margin="28,179,0,0" VerticalAlignment="Top" Width="116" Click="SeleectButton_Click"/>
</Grid>
</Window>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WpfApp1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void ItemI_Selected(object sender, RoutedEventArgs e)
{
StuffToShow.Text += "\nOne";
}
private void Item2_Selected(object sender, RoutedEventArgs e)
{
StuffToShow.Text += "\nTwo";
}
private void SeleectButton_Click(object sender, RoutedEventArgs e)
{
ThanklessListBox.SelectedItem = 1; //Choose Dos
}
private void ResetListBox_Click(object sender, RoutedEventArgs e)
{
ThanklessListBox.SelectedItem = -1; //Deselect
}
}
In your code behind, you are using SelectedItem with an integer.
private void ResetListBox_Click(object sender, RoutedEventArgs e)
{
ThanklessListBox.SelectedItem = -1; //Deselect
}
Try either using SelectedIndex
private void ResetListBox_Click(object sender, RoutedEventArgs e)
{
ThanklessListBox.SelectedIndex = -1; //Deselect
}
Or Selected Item with null
Edited to add: You could also do
ThanklessListBox.SelectedItems.Clear
which is what I think the other person whose post is now deleted meant>
In fairness, this is something you could really learn just by browsing the online documentation for ListBox on the MS site
I cannot find a similar question or answer to what I am asking but if there is one out there I do apologize. What I am looking to achieve is to simply loop through all my controls in a user control and then write to a string builder in the order of the loop.
The code below outlines a simple example and I did try some limited things based on me being knew to C# etc.
<Window x:Class="CopyandPaste.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:CopyandPaste"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid x:Name="MainGrid">
<Button x:Name="CopyButton" Content="Copy Button" HorizontalAlignment="Left" Margin="10,34,0,0" VerticalAlignment="Top" RenderTransformOrigin="-4.265,-0.098" Height="41" Width="120" Click="CopyButton_Click"/>
<Grid x:Name="MasterGrid" HorizontalAlignment="Left" Height="378" Margin="146,10,0,0" VerticalAlignment="Top" Width="572">
<TextBox HorizontalAlignment="Center" Margin="0,21,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="408" Height="23" Grid.Column="1"/>
<RadioButton x:Name="RadioButton" Content="RadioButton" HorizontalAlignment="Left" Margin="82,55,0,0" VerticalAlignment="Top" Height="15" Width="85"/>
<ComboBox x:Name="ComboBox" HorizontalAlignment="Left" Margin="82,95,0,0" VerticalAlignment="Top" Width="369" Height="22">
<ComboBoxItem>THIS IS IT 1</ComboBoxItem>
<ComboBoxItem>THIS IS IT 2</ComboBoxItem>
<ComboBoxItem>THIS IS IT 3</ComboBoxItem>
</ComboBox>
<TextBox HorizontalAlignment="Center" Margin="0,140,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="408" Height="23"/>
<TextBox HorizontalAlignment="Center" TextWrapping="Wrap" VerticalAlignment="Center" Width="408" RenderTransformOrigin="0.333,0.782" Height="28"/>
</Grid>
</Grid>
</Window>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace CopyandPaste
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void CopyButton_Click(object sender, RoutedEventArgs e)
{
bool first = true;
StringBuilder value = new StringBuilder();
// some loop here
Clipboard.SetText(value.ToString());
}
}
}
I played with some foreach loops that were nested but of course got some results that were unwanted:
1
RadioButton
THIS IS IT 2
2
RadioButton
THIS IS IT 2
3
RadioButton
THIS IS IT 2
I understand what is going on here where the text box is causing the loop to continue. Trying to get some ideas or a point in the right direction to achieve an output like:
1
RadioButton
THIS IS IT 2
2
3
Any WPF UIElement has a Children property which will give you all its child controls. So you can use it to enumerate children and then loop through them. Something like;
foreach (var child in MasterGrid.Children)
{
// string builder code
}
You haven't quite clearly explained what your criteria to display a control is, but from the limited explanation you've given it looks like you want to grab the Text property if it's a TextBox, the SelectedItem if it is a ComboBox, and the name of the control if it is a RadioButton. These are quite different things when it comes to a control, so inside the loop you will have to check the type of each child control and get the right information.
private void CopyButton_Click(object sender, RoutedEventArgs e)
{
StringBuilder value = new StringBuilder();
foreach (var child in MasterGrid.Children.OfType<Control>())
{
if (child.GetType() == typeof(TextBox))
{
value.Append(((TextBox)child).Text + Environment.NewLine);
}
else if (child.GetType() == typeof(RadioButton))
{
var rb = (RadioButton)child;
if (rb.IsChecked == true)
{
value.Append(rb.Name + Environment.NewLine);
}
}
else if (child.GetType() == typeof(ComboBox))
{
value.Append(((ComboBox)child).Text + Environment.NewLine);
}
}
MessageBox.Show(value.ToString());
}
Above is for the types of controls you've mentioned, you'll have to figure out what to do with other control types.
Next when it comes to order, there can be different meanings to the 'order' in controls in a WPF GUI.
Do you want the order in which they are listed in the XAML code?
Or do you want the order in which they are displayed when the program is run?
For example, in your code if you moved the last text box XAML code above the second-to-last, they will still appear in the original order when you run the program because you've hard-coded their locations (which in itself is a bad idea; you should use grids, stack panels etc to do your layout in WPF).
I think if you care about the order, best option is to modify your XAML and specify the Tag property of each control.
E.g.
<TextBox Grid.Column="1"
Width="408"
Height="23"
Margin="0,21,0,0"
HorizontalAlignment="Center"
VerticalAlignment="Top"
Tag="1"
TextWrapping="Wrap"/>
Then when you enumerate the children, do an order by tag before iterating through them.
This way you have firm control over whatever it is that you mean by order.
var children = MasterGrid.Children.OfType<Control>().OrderBy(x => x.Tag);
foreach (var child in children)
{
// Same as before
}
I need to create interactive menu. When option was choosen, I want to show appropriate content.
For example when option "Schemat bazy Northwind" was clicked, to my grid should be added Image. When another option was choosen previous content is removed and etc.
The only thing that comes to my mind is create functions which at the beginning clear grid and later add content(Is it possible?).
Please there anybody could direct me to solve this problem.
<Window x:Class="Northwind.AdminPanel"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Panel administratora" WindowState="Maximized">
<StackPanel Name="bindingData">
<StatusBar>
<TextBlock FontSize="15" Text="{Binding ServerName}" Margin="0 0 30 0"></TextBlock>
<TextBlock FontSize="15" Text="{Binding ConnectionStatus}" Margin="0 0 30 0"></TextBlock>
<Label FontSize="15" Name="lblClock"></Label>
</StatusBar>
<DockPanel Height="55">
<Menu DockPanel.Dock="Top">
<MenuItem Header="Baza" Margin="10" FontSize="15"></MenuItem>
<MenuItem Header="Pomoc" Margin="10" FontSize="15">
<MenuItem x:Name="itemSchema" Header="Schemat bazy Northwind" Click="itmSchema_Click_1"></MenuItem>
</MenuItem>
</Menu>
</DockPanel>
<Grid x:Name="mainContent">
<!--add content -->
</Grid>
</StackPanel>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Windows.Threading;
namespace Northwind
{
public partial class AdminPanel : Window
{
public string ServerName { get; set; }
public string ConnectionStatus { get; set; }
public AdminPanel(string name,string status)
{
InitializeComponent();
this.ServerName = name;
this.ConnectionStatus = status;
DispatcherTimer dtClockTime = new DispatcherTimer();
dtClockTime.Interval = new TimeSpan(0, 0, 1);
dtClockTime.Tick += dtClockTime_Tick;
dtClockTime.Start();
bindingData.DataContext = this;
}
private void dtClockTime_Tick(object sender, EventArgs e)
{
lblClock.Content = DateTime.Now.ToLongTimeString();
}
private void itmSchema_Click_1(object sender, RoutedEventArgs e)
{
//code
}
}
}
You can put the menu or whichever item you wanted to a conatainer (Grid) and you can use the Visibility attribute as collapsed when you want to hide that control.
if you are not using MVVM pattern then add it into the corresponding Event.
Container_Name.Visibility = Visibility.Collapsed;
Or else you can use the Xaml Triggers for obtain the same.
For that refer StackOverflow_Answer
Create a resources Dictionary and add this code
<StackPanel xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<!-- Set names two different ways -->
<Button Name="okButton">OK</Button>
<Button x:Name="cancelButton">Cancel</Button>
<ListBox>
<!-- Set content three different ways -->
<ListBoxItem Content="Item 1" />
<ListBoxItem>Item 2</ListBoxItem>
<ListBoxItem>
<ListBoxItem.Content>Item 3</ListBoxItem.Content>
</ListBoxItem>
</ListBox> </StackPanel>
when option "Schemat bazy Northwind" was clicked
private void SchematbazyNorthwind_Click(object sender, RoutedEventArgs e)
{
StackPanel stackPanel = null;
using (FileStream fs =
new FileStream("Dictionary1.xaml", FileMode.Open, FileAccess.Read))
{
stackPanel = (StackPanel)XamlReader.Load(fs);
}
MainGrid.Children.Add(stackPanel);
}
Load your Resources and attach to you grid
I'm developing a form and one of the requirements for it is that the majority of the fields be disabled until the first two have been completed. For the sake of usability I want it set up so after you tab out of the second field (Field_Two.LostFocus) the rest of the fields are enabled, displayed, and the first of those fields is focused. The code that I have currently sets all fields' visibility to visibility.hidden at startup. What it currently does is focus Field_One (next in the tab order of enabled fields), but I've confirmed that the conditions are properly satisfied and that execution proceeds past the return statement.
Field.beenFocused is a variable I've created that is initialized as false and then set to true when the Field is focused for the first time, my Field class extends TextBox; all of my controls save Field_One and Field_Two are in Stackpanels.
C#
void Field_Two_LostFocus(object sender, RoutedEventArgs e)
{
if (!Field_Three.beenFocused)
{
if (String.IsNullOrWhiteSpace(Field_One.Text) || String.IsNullOrWhiteSpace(Field_Two.Text))
return;
foreach (object u in ApplicationGrid.Children)
if (u.GetType() == typeof(StackPanel))
((StackPanel)u).IsEnabled = true;
do { Field_Three.Focus(); }
while (!Field_Three.beenFocused);
}
}
You could try enabling/disabling in a TextChanged event, rather than a LostFocus event.
Here's some sample code.
MainWindow.xaml:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StackPanel>
<TextBox Name="textBox1" TextChanged="ValidateInitialFieldsOnChange"
Height="23" Width="120" />
<TextBox Name="textBox2" TextChanged="ValidateInitialFieldsOnChange"
Height="23" Width="120" />
<TextBox Name="textBox3" IsEnabled="False" Height="23" Width="120" />
</StackPanel>
</Window>
MainWindow.xaml.cs:
using System.Windows;
using System.Windows.Controls;
namespace WpfApplication1
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void ValidateInitialFieldsOnChange(object sender,
TextChangedEventArgs e)
{
textBox3.IsEnabled = !string.IsNullOrWhiteSpace(textBox1.Text)
&& !string.IsNullOrWhiteSpace(textBox2.Text)
;
}
}
}
It would be fairly trivial to adapt this code to suit your scenario, and wouldn't require manually setting focus. You could probably rely on tab order instead.
But if tab order doesn't help, you can still use a combination of these approaches to solve the problem. Set focus in the LostFocus event, and enable in teh TextChanged event.
I have a situation where I am using wpf data binding and validation using the ExceptionValidationRule.
Another part of the solution invovles collapsing some panels and showing others.
If a validation exception is set - i.e. the UI is showing a red border around the UI element with the validation problem, and the containing panel is collapsed, the red border is still displayed. This is clearly not meant to be? Is there a workaround for this? Anyone know if this is by design?
Minimal code example provided (not my actual code, but replicates the problem). Create a new WpfApplication (I called mine WpfDataBindingProblem).
The xaml for window1 is as follows:
<Window x:Class="WpfDataBindingProblem.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<StackPanel Margin="5">
<StackPanel Name="panel1" Visibility="Visible" Margin="5">
<TextBox Name="DataBoundTextBox">
<Binding Path="TextValue">
<Binding.ValidationRules>
<ExceptionValidationRule/>
</Binding.ValidationRules>
</Binding>
</TextBox>
</StackPanel>
<StackPanel Name="panel2" Visibility="Collapsed" Margin="5">
<TextBlock>
The quick brown fox jumps over the lazy dog.
</TextBlock>
</StackPanel>
<Button Click="Button_Click" Margin="5">
Toggle panels
</Button>
</StackPanel>
</Window>
The code for window1 is as follows:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WpfDataBindingProblem {
public partial class Window1 : Window {
public Window1() {
InitializeComponent();
this.DataContext = new MyClass("default");
}
private void Button_Click(object sender, RoutedEventArgs e) {
panel1.Visibility = panel1.Visibility == Visibility.Collapsed ?
Visibility.Visible : Visibility.Collapsed;
panel2.Visibility = panel2.Visibility == Visibility.Collapsed ?
Visibility.Visible : Visibility.Collapsed;
}
}
public class MyClass : INotifyPropertyChanged {
private string mTextValue;
public MyClass(string defaultText) {
TextValue = defaultText;
}
public string TextValue {
get {
return mTextValue;
}
set {
mTextValue = value;
if (string.IsNullOrEmpty(mTextValue)) {
throw new ApplicationException("Text value cannot be empty");
}
OnPropertyChanged(new PropertyChangedEventArgs("TextValue"));
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(PropertyChangedEventArgs e) {
if (this.PropertyChanged != null) {
this.PropertyChanged(this, e);
}
}
}
}
To reproduce the problem, run the application. Delete the default text from the textbox and tab off - red rectangle is shown indicating a validation problem. Click the button. Panel containing control with red rectangle is hidden and another panel is shown, but the red rectangle remains. Aargh!
All help much appreciated.
PS apologies for long question title!
If I remember correctly, this is a known issue. We re-templated textbox to include the following:
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<ControlTemplate.Resources>
<BooleanToVisibilityConverter x:Key="converter" />
</ControlTemplate.Resources>
<DockPanel LastChildFill="True">
<Border
BorderThickness="1"
BorderBrush="Red"
Visibility="{Binding ElementName=placeholder, Mode=OneWay, Path=AdornedElement.IsVisible, Converter={StaticResource converter}}">
<AdornedElementPlaceholder x:Name="placeholder" />
</Border>
</DockPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
I have an answer to the problem myself which is to change my button click event which changes the visibility of the panels. This would change to something like this:
private void Button_Click(object sender, RoutedEventArgs e) {
if (panel1.Visibility == Visibility.Collapsed) {
panel1.Visibility = Visibility.Visible;
DataBoundTextBox.GetBindingExpression(TextBox.TextProperty).UpdateSource();
panel2.Visibility = Visibility.Collapsed;
}
else {
panel1.Visibility = Visibility.Collapsed;
DataBoundTextBox.GetBindingExpression(TextBox.TextProperty).UpdateTarget();
panel2.Visibility = Visibility.Visible;
}
}
The UpdateSource() and UpdateTarget() have the effect of reapplying and removing the red rectangle, but this seems like an ugly hack. Surely the wpf framework should be hiding the red rectangle for me when the containing panel is collapsed. Any cleaner fix that doesn't require me to fiddle with the binding expression gets my vote.
Thanks,
Sam