Update UI by code in WPF - c#

I'm trying to update some user control in wpf by code, with no luck.
That's the xaml:
<UserControl x:Class="SimuladorNocs.UI.Diagram.PropertiesWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:PropertyGrid="clr-namespace:Deepforest.WPF.Controls"
>
<DockPanel>
<StackPanel x:Name="stackPanel" Width="300" Height="600" HorizontalAlignment="Center">
<PropertyGrid:PropertyGridControl Height="300" x:Name="MyPropertyGrid" />
</StackPanel>
</DockPanel>
and that's the c# code:
public void SetInstance(object obj){
MyPropertyGrid = new PropertyGridControl { Instance = obj, Height = 300 };
stackPanel.Children.Clear();
stackPanel.Children.Add(MyPropertyGrid); }
In the end, the property appers to be changing, but I was unable to see the changes in the UI. I also tried to create a new object instead of using the existing MyPropertyGrid, did not work, also tried not clearing the stackpanel without success...
What am I missing?
Thanks

stackPanel.InvalidateVisual();
Please add this at the last line.

I don't have the specified propertygrid control but it seems that the UI doesn't get updated. did you try "UpdateLayout()" on that control and on the stack panel itself ?

Swapped out the PropertyGridControl for a Label and it worked fine. I suggest you do the same. If it works, it's more a question of what the PropertyGridControl is doing wrong...

Related

MVVM Binding not working in design-time

I tried to bind the visibility of a few buttons to some booleans in a viewmodel and make it work in design-time. I did this several times and never had a problem, but now it does not work and I don't have a clue why. Note that everything works
fine when I run the application.
I extracted the essence into a separate app and it still doesn't work!
My XAML:
<Window x:Class="BindingTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:bindingTest="clr-namespace:BindingTest"
Title="MainWindow" Height="350" Width="525"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance bindingTest:TestViewModel, d:IsDesignTimeCreatable=true}">
<Grid>
<Grid.Resources>
<BooleanToVisibilityConverter x:Key="BoolToVis"/>
</Grid.Resources>
<StackPanel>
<Button Visibility="{Binding IsButton1Visible, Converter={StaticResource BoolToVis}}">Hallo 1</Button>
<Button Visibility="{Binding Button2Visibility}">Hallo 2</Button>
<Button>Hallo 3</Button>
</StackPanel>
</Grid>
</Window>
My ViewModel:
public class TestViewModel
{
public bool IsButton1Visible
{
get { return true; }
}
public Visibility Button2Visibility
{
get { return Visibility.Hidden; }
}
}
To make it work in the real app, i added to the constructor of the XAML:
DataContext = new TestViewModel();
This is all pretty simple, but why is it not working in the designer?? I always got this to work in the past and now I tried for hours... It's not the only binding not working, but why is not even this working??
Expected Result:
Button1 visible
Button2 hidden
Button3 visible
Result in the designer:
Button1 collapsed
Button2 visible
Button3 visible
UPDATE: The problem with design-time DataContext bindings not working is due to mistakenly using the d: namespace prefix for the IsDesignTimeCreatable property.
So, change
d:IsDesignTimeCreatable=True
to
IsDesignTimeCreatable=True
and everything should be fine. (My bug report filed with MS will be updated with this information as well.)
As this problem with the design-time DataContext bindings not working was consistently reproducable in VS2015 as well as VS2013 when IsDesignTimeCreatable is prefixed with the d: namespace (see comments below the question), i decided to file a bug report with Microsoft: Issue #1651633 "WPF designer: Designtime DataContext bindings broken?".
Lets see how Microsofts will follow-up with regard to this issue. It should be addressed, since such an issue can catch a developer off-guard and make him reinstall Visual Studio for no benefit... ;)
If anything is OK with the code, there could be an other tricky problem:
In the Designer of Visual Studio a new button was introduced in 2019, which enables / disables the preview of design data.
It's a very tiny button on botton left of the designer window. It's tooltip is "Enable Project Code".
Click this important toggle button to see the design data. (But be aware that you don't disable it, if it's already enabled.)

WPF ContextMenu = {x:Null} but still shows menu inside ContentControl

I need disable standard ContextMenu of TextBox. I've created a new WPF project and added the following:
<Window x:Class="WpfApplication3.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<ContentControl>
<ContentControl.ContentTemplate>
<DataTemplate>
<TextBox ContextMenu="{x:Null}" VerticalAlignment="Top" HorizontalAlignment="Left" Width="50"></TextBox>
</DataTemplate>
</ContentControl.ContentTemplate>
</ContentControl>
</Grid>
</Window>
But this is what i get :
The following code works fine :
<Grid>
<TextBox ContextMenu="{x:Null}" VerticalAlignment="Top" HorizontalAlignment="Left" Width="50"></TextBox>
</Grid>
Why is this happening?
Update.
According to the accepted answer I've created a class derived from TextBox in order to be able to show parents ContextMenu.
public class TextBoxNoMenu: TextBox
{
public TextBoxNoMenu()
{
ContextMenu = null;
}
}
Why is this happening?
This is an interesting case of a control's behavior changing depending on where/how a property is set.
TextBox provides its own context menu by default. The only time it won't do this is when you explicitly set the local value of ContextMenu to null. This is what happens in your simple example where the TextBox is directly within in the Grid.
However, when you set a property inside a template, you're not actually setting a local value; you're setting a "parent template" value. If you inspect the value with DependencyPropertyHelper.GetValueSource(), you'll see the base value source is ParentTemplate instead of Local. Thus, the menu still gets overridden.
See Dependency Property Value Precedence for more information about the different kinds of dependency property value sources.
#OmegaMan's suggestion of assigning a 'hidden' context menu seems to work pretty well.
Note that while you mayhave disabled the ContextMenu on TextBox, if it's in another control, you may actually be seeing the ContextMenu of such a wrapper. Try Snooping it to see more specifically this sort of behaviour.
Note also that many of the default Control Templates throughout WPF can cause issues such as these by adding their own child objects. Seeing the default template for TextBox uses a Border and then <ScrollViewer Margin="0" x:Name="PART_ContentHost" />, you're likely seeing the ContextMenu of a child object if TextBox.
This seems to be a running issue where X:Null does not 'turn off' the default context menu. A better way would be to change it's visiblity:
<TextBox.ContextMenu>
<ContextMenu Visibility="Collapsed"/>
</TextBox.ContextMenu>
I had a similar issue, but I was generating my controls programmatically, and my parent control is a dockpanel. Based on the accepted answer, I decided to set the null value in the code behind.
<Grid>
<DockPanel>
<TextBox Name="txtBox" VerticalAlignment="Top" HorizontalAlignment="Left" Width="50"></TextBox>
</DockPanel>
</Grid>
and then
private void Window_Loaded(object sender, RoutedEventArgs e)
{
txtBox.ContextMenu = null;
}
EDIT: I felt this was kind of a haphazard answer, as it doesn't fully or directly solve this question. I did some digging and if you implement the method found in the answer to This Question you can find the textbox in the code-behind.
So, if you have this
<Grid>
<ContentControl>
<ContentControl.ContentTemplate>
<DataTemplate>
<TextBox Name="txtBox" VerticalAlignment="Top" HorizontalAlignment="Left" Width="50"></TextBox>
</DataTemplate>
</ContentControl.ContentTemplate>
</ContentControl>
</Grid>
Then you should be able to find your textbox by name (txtBox in this case) and set the context menu to null
TextBox myTextBox = FindChild<TextBox>(Application.Current.MainWindow, "txtBox");
myTextBox.ContextMenu = null;
Personally I'd prefer this to creating a new class with inheritance, but whatever works for you. This still doesn't answer "Why is this happening?" but I think the accepted answer does a good job of that.

MouseDown event of image in usercontrol not fireing

I made a usercontrol in WPF with an image in it. I declared a MouseDown event for this image:
<Image x:Name="imgState" Height="300" Width="300" MouseDown="imgState_MouseDown" OpacityMask="#00000000" />
I placed this usercontrol on my application form, but the event isn't fireing. I'm pretty new to WPF and I read about RoutedEvents but I don't really understand it. I would be happy if someone could help and explain this to me!
Update
Changing to PreviewMouseDown didn't fire the event too. I tried setting the background to transparent and even tried with a blank 300x300 image. The grid workaround doesn't fire the event too. Here is how my code behind looks like:
private void imgState_MouseDown(object sender, MouseButtonEventArgs e)
{
//Some code here
}
Update 2
Here is my whole XAML file:
<UserControl x:Class="TicTacToe.controls.SingleField"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<Image x:Name="imgState" MouseDown="imgState_MouseDown" Height="300" Width="300" Stretch="None" OpacityMask="#00000000"/>
</Grid>
</UserControl>
I removed the source again because I set one from code behind at runtime and adding a transparent/clear image didn't helped.
You probably want PreviewMouseUp instead of MouseDown event
<Image x:Name="imgState" Height="300" Width="300"
PreviewMouseUp="ImgState_OnPreviewMouseUp"
PreviewMouseDown="ImgState_OnPreviewMouseDown"/>
Either of the two, you can capture the event from there.
If the answer above does not help:
Not a very nice solution but does work so many times:
Wrap your image with a grid on which you will have your event...
<Grid MouseDown="imgState_MouseDown">
<Image/>
</Grid>
Okay I solved the problem myself.
The problem was the setting OpacityMask="#00000000" that prevented the image from appearing so there were, as #lll said, nothing to hit. I don't know when the setting was set, but I think it happened automatically while expanding the Representation tab.
Thanks for helping me!

Focus Manager issue in wpf

I have Popup window where dynamically attaching the UserControl. Here I need to set the focus for first control. If I use:
FocusManager.FocusedElement="{Binding ElementName=txtcode}"
on UserControl the cursor not coming. Could anyone help me to set focus on first element in the UserControl.
Thanks in advance.
I have just needed to do this, but not in a user control, so might not help. what I needed to do is to add the FocusManager bit in the Window tag:
<Window x:Class="xxxxx"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" FocusManager.FocusedElement="{Binding ElementName=txtcode}">
And then make sure i correctly named the control:
<TextBox Name="txtcode" Text="" />
Although I'm new to wpf, and haven't worked with user controls yet.

Adding a WPF UserControl programmatically has no style

I'm trying to create a button-like UserControl which consists of a border and a label. When adding this UserControl directly in the XAML of MainWindow, it renders correctly (it is put in a WrapPanel), but if I add it programmatically it doesn't look the same at all. There is no border, no background color, the text size of the label is wrong and so is the text color.
This is my user control:
<UserControl x:Class="Jishi.SonosPartyMode.UserControls.Player"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="150" d:DesignWidth="300"
Width="200"
Height="100">
<Border BorderBrush="#086EAA" CornerRadius="8,8,8,8" BorderThickness="4" Margin="15" Padding="15px" VerticalAlignment="Center" Background="#0A4069">
<Label Name="PlayerName" TextElement.Foreground="White" TextElement.FontSize="20px">asdasdasd</Label>
</Border>
</UserControl>
when adding it, I just invoke it like this:
var button = new Player { Content = player.Properties.RoomName, DataContext = player.Properties.UDN };
PlayerList.Children.Add( button );
PlayerList is the actual WrapPanel and Player is my UserControl. I have tried finding information regarding this, but I don't find anything. If you have another approach that I can take, please come with suggestions. All I want is a clickable area with some rounded corners that can contain text (one or more rows).
I can apply styles programatically, but the styles defined in the xaml for the UserControl isn't preserved (Border, Margins, colors etc).
First of all, you don't need to create a custom control for this, you can easily do
var button = new Border { *border properties*, Content = new Lable {Content="dfsdfsdfsd"}};
And if you use PlayerList.Children.Add( button ); then it adds to the end of Wrappanel and in XAML code you add it not as the last element (maybe)..
And the last idea is that you lost some properties that you added in XAML when test it (like aligment, margin, etc.)
Hope this helps.

Categories