I'm quite new to c# wpf and have a problem.
I have used the answer from this post to duplicate a Grid control. The grid control contains a button. It looks like it is being duplicated correctly.
When the original control's button is pressed, the click event is handled which calls a method in the window's code.
When the copy of the control's button is pressed, the click event is not fired and the method is not called. This is confusing me as I want it to call that same method.
Maybe the event handling data is not being copied properly? Is there a way around this?
Both the origional grid and copied grid (containing the buttons) are children of another grid.
Edit:
This is the xaml for the origional grid which contains a button:
<Grid Name="TempTab" DockPanel.Dock="Left" HorizontalAlignment="Left" Margin="5,5,5,0">
<Rectangle Fill="Black" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Stroke ="White" Margin="0,0,-2,0">
</Rectangle>
<Grid>
<DockPanel LastChildFill="False">
<TextBlock Foreground="White" HorizontalAlignment="Left" VerticalAlignment="Bottom" Margin="3,0,3,3">Some Text</TextBlock>
<Button Width="50" BorderBrush="{x:Null}" Foreground="{x:Null}" BorderThickness="0" Margin="3,0,0,0" Click="tabdowntest">
<Button.Background>
<ImageBrush ImageSource="TopMenuBar_Close.png" Stretch="Uniform"/>
</Button.Background>
</Button>
</DockPanel>
</Grid>
</Grid>
This grid is a child of a DockPanel with name 'TabsDock'.
It is being copied with the following code:
string gridXaml = XamlWriter.Save(TempTab);
StringReader stringReader = new StringReader(gridXaml);
XmlReader xmlReader = XmlReader.Create(stringReader);
Grid newTab = (Grid)XamlReader.Load(xmlReader);
TabsDock.Children.Add(newTab);
This is the code for the 'Click' event handler which should be called when the either the origional or the copied button's are pressed. But it is only called for the origional:
private void tabdowntest(object sender, MouseButtonEventArgs e)
{
Console.WriteLine("Button Pressed");
}
The bindigs are not set, you need to set them (comment in the orig post):
To be clear, this is only half the solution (as it stood back in 08). This will cause bindings to be evaluated and the results be serialized. If you wish to preserve bindings (as the question asked) you must either add a ExpressionConverter to the Binding type at runtime (see the second part of my question for the relevant link) or see my own answer below for how to do it in 4.0.
Related
I'm trying to programatically create a button flyout, within my XAML I have:
<Page.Resources>
<Button x:Key="LaunchFlyout" Content="LAUNCH">
<Button.Flyout>
<Flyout Placement="Top">
<Grid Width="200" Height="200">
<StackPanel>
<Rectangle Fill="Red" Width="100" Height="100" />
<Rectangle Fill="Green" Width="100" Height="100" />
</StackPanel>
</Grid>
</Flyout>
</Button.Flyout>
</Button>
</Page.Resources>
Nested within grids I have:
<Grid x:Name="launchBtn_grid" Grid.Column="1">
</Grid>
And then in my code within the Page_Loaded method I have:
bool hasContainer = localSettings.Containers.ContainsKey("appStatus");
if (!hasContainer) {
Button button = (Button)this.Resources["LaunchFlyout"];
launchBtn_grid.Children.Add(button);
}
else {
Button button = new Button();
button.Content = "LAUNCH";
button.Click += launch_btn_Click;
launchBtn_grid.Children.Add(button);
}
When I debug this, it reaches the IF statement and reaches this line launchBtn_grid.Children.Add(button); and then I get this error Element is already the child of another element.
Does anyone understand why? I have already looked and they dont already exist so I don't understand why it is giving me this error. Does anyone know what I am doing wrong?
I'm not sure in what context/use case your are doing that, but it feels weird to me to have an actual control as a Resource (not a DataTemplate, Style, etc).
If you only want to have 1 button of the 2 different template, why not switch Visibility on the 2 instead of loading controls from your code behind ?
Going forward with the idea, just add both buttons in the Grid within your XAML and switch their Visibility according to the setting you read.
There is a BooleanToVisibilityConverter within the framework to help you with this.
I am new to windows dev't and C#, how do make those texts i posted in the code navigate to another xaml page?
Thanks
<StackPanel>
<TextBlock Text="contact us"
TextWrapping="Wrap"
Style="{StaticResource PhoneTextExtraLargeStyle}"
FontSize="{StaticResource PhoneFontSizeExtraLarge}"/>
<TextBlock Text="help"
TextWrapping="Wrap"
Style="{StaticResource PhoneTextExtraLargeStyle}"
FontSize="{StaticResource PhoneFontSizeExtraLarge}"/>
</StackPanel>
There are several ways to do this. Based on what you've described, one way would be to link an event to a Window.Show() method, to show the window. See the links I've provided here for some examples and thoughts, but basically you could insert this into a TextBlock to cause a method to happen when you do a mouse-click on it:
<TextBlock Text="contact us"
TextWrapping="Wrap"
Style="{StaticResource PhoneTextExtraLargeStyle}"
FontSize="{StaticResource PhoneFontSizeExtraLarge}"
MouseUp="MethodToCallNameHere"/>
When you write this in XAML, highlight "MethodToCallNameHere" and press F12, and it will automatically insert a method for you in that Window's code-behind. You can then put in your new window's class there with .Show().
For example, if you wanted to show a new window that is an AboutWindow class (i.e., when you created another XAML window, you named it "AboutWindow"), you could highlight "MethodToCallNameHere" and press F12.
Then, in the created method in the code-behind, you could make it look something like this, to open "AboutWindow" window when the TextBlock is clicked:
private void MethodToCallNameHere(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
// instantiate the new Window's class
AboutWindow aboutWindow = new AboutWindow();
// call the .Show() method to show the new window
aboutWindow.Show();
}
I'd recommend looking through MS's online (and free) documentation on WPF applications here. It's been very helpful to me as I've been learning.
This is a really weird bug. I have no idea why it could be happening. I know that posting it here is a bit of a long-shot, but I'm out of other ideas.
I have two ListBoxs that act as menus.
<ListBox Margin="56,8,15,0" FontSize="64"
ItemsSource="{Binding FavoriteSections}"
SelectionChanged="MenuList_SelectionChanged">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<toolkit:ContextMenuService.ContextMenu>
<toolkit:ContextMenu>
<toolkit:MenuItem Header="Remove" Click="FavoritesContextMenuItem_Click" />
</toolkit:ContextMenu>
</toolkit:ContextMenuService.ContextMenu>
<TextBlock Text="{Binding DisplayName}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<ListBox x:Name="sectionList" Margin="56,8,15,0" FontSize="64"
SelectionChanged="MenuList_SelectionChanged"
ItemsSource="{Binding SectionViewModels}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<toolkit:ContextMenuService.ContextMenu>
<toolkit:ContextMenu>
<toolkit:MenuItem Header="Add to favorites" Click="SectionContextMenuItem_Click" />
</toolkit:ContextMenu>
</toolkit:ContextMenuService.ContextMenu>
<TextBlock Text="{Binding DisplayName}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
The bug exists across both of them.
When the selection changes on either menu, this method is called:
void MenuList_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (e.AddedItems.Count == 0)
{
return;
}
Uri page = null;
object selected = e.AddedItems[0];
if (selected is NavigableItem)
{
NavigableItem selectedItem = (NavigableItem)selected;
page = selectedItem.Page;
}
else if (selected is SectionViewModel)
{
SectionViewModel selectedVM = (SectionViewModel)selected;
page = selectedVM.Section.Page;
}
Debug.Assert(page != null, "What is the type of `selected`?");
// if I comment out this line, the problem goes away:
NavigationService.Navigate(page);
ListBox selectedBox = (ListBox)sender;
selectedBox.SelectedIndex = -1;
}
If I comment out the NavigationService.Navigate() line, the problem goes away. If I replace the line with a different URI, the problem remains.
About 70% of the time, when I click on a menu item, the content jumps all over the page. (The remaining 30%, no bug occurs.) It happens too quickly to see what's really going on, but different UI elements overlap each other.
This only occurs the first time I click on something in those menus during the app's lifetime. If I hit "back" then select a menu item again, the problem will not occur.
What could be happening here? I really have no idea. The code-behind doesn't have a OnNavigatedFrom method, so I don't think it's a problem there.
I'm using Silverlight for Windows Phone 7
Update: Mysteriously, I can't seem to reproduce this in the debugger - only after deploying the app and running it in the emulator unattached. ???
Update 2: The bug appears when NavigationService.Navigate() is called from the Click event handler of a button, as well:
<Button Content="Foo" Click="Button_Click" Grid.Row="0"/>
private void Button_Click(object sender, RoutedEventArgs e)
{
NavigationService.Navigate(new Uri("/Views/sections.xaml?section=43", UriKind.Relative));
}
Looks like the bug has to do with the navigation, not the UI element used to trigger the call.
Update 3: More weirdness. Still not able to reproduce the app while the debugger is attached. If I make the loading progress bar always collapsed, the bug disappears:
<ProgressBar x:Name="LoadingProgressBar"
IsIndeterminate="True"
Visibility="Collapsed"
Style="{StaticResource PerformanceProgressBar}"
VerticalAlignment="Top"/>
Alternatively, commenting out this line in code-behind makes the bug disappear:
LoadingProgressBar.Visibility = Visibility.Collapsed;
I really don't understand what's going on here. That line of code is not executed when the page is navigated from.
Here is the full XAML of the control that's getting messed up:
<ProgressBar x:Name="LoadingProgressBar"
IsIndeterminate="True"
Visibility="Collapsed"
Style="{StaticResource PerformanceProgressBar}"
VerticalAlignment="Top"/>
<TextBlock x:Name="DownloadFailed"
Visibility="Collapsed"
Style="{StaticResource disabledText}"
Margin="56,8,8,-8" >
FooBar.com could not be reached. Do you have a network connection?
</TextBlock>
<ListBox x:Name="sectionList" Margin="56,8,15,0" FontSize="64"
SelectionChanged="MenuList_SelectionChanged"
ItemsSource="{Binding SectionViewModels}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<toolkit:ContextMenuService.ContextMenu>
<toolkit:ContextMenu>
<toolkit:MenuItem Header="Add to favorites" Click="SectionContextMenuItem_Click" />
</toolkit:ContextMenu>
</toolkit:ContextMenuService.ContextMenu>
<TextBlock Text="{Binding DisplayName}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</controls:PivotItem>
The problem lies in your usage of the Indeterminate ProgressBar. All its animations are done on the UI thread, and not the Compositor thread, as is the usual practise. Since you are already using the Windows Phone Toolkit, you can easily replace your ProgressBar with the PerformanceProgressBar offered by the toolkit. This should solve your problems.
Before I begin, let me say that I don't have a lot of experience with Windows Phone, so my answers are based on more generic WPF knowledge, so forgive me if I'm overlooking specifics of the platform, or am referencing features not available.
Some diagnostic questions (sorry this isn't a direct answer):
Firstly, it does seem like Navigate is calling a lot of layoutUpdates. I haven't yet seen what type of container is containing the pages you're updating, but it is worth asking, is that also being disrupted or only the menus?
Secondly, could you try specifying your itemPanel explicitly? You're expecting them to be virtualizingStackPanels, but you may find that some parent object in your visual hierarchy is creating a different inheritance scenario.
You have these in a grid, which is meant to size to its content, or take the default size (100x100 in normal WPF) or take sizing from its parent, which without knowing how you've specified the grid, or the grid's parent, it's difficult to know its behaviour. Furthermore, Grids automatically z-order their children according to the order in which they were added. Can you determine whether it is just the layout of the lisboxes that is being disturbed, or whether it is the entire grid? Or, is it larger than that?
If you attach to the layoutUpdated() event of the listboxes, grid, or grid's parent, you should be able to look at the stacktraces that lead you there - it sounds to me that you'll find that layoutUpdated() is firing more than you'd like it to. Further, you'll be able to output the heights and widths (ActualHeight etcetera of course) during those steps so that you can see when exactly those changes happen.
I hope that some of these diagnostic steps might help you reach an answer.
I am having an issue with my button event not occuring
Basically I have cart items that are listed in the listbox. When the delete button is clicked then the item is deleted from the list box.
I tried debugging, but it seems to not even call the method for when the button is clicked.
In my ticketscreen.xaml file I specify my button in the template:
<DataTemplate x:Key="TicketTemplate">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left" Height="50">
...
<Button Name="Remove" Width="35" Height="35"
FontFamily="Resources/#charlemagnestd-regular.otf" FontSize="24"
Click="removeCartItem" Grid.Column="5"
MouseMove="Remove_MouseMove">X</Button>
...
</StackPanel>
</DataTemplate>
My List box is the following:
<ListBox Name="TicketItems" ItemsSource="{Binding}"
ItemTemplate="{StaticResource TicketTemplate}"
Grid.Row="3" Grid.ColumnSpan="6" Background="Transparent"
BorderBrush="Transparent" IsHitTestVisible="False">
</ListBox>
My method removeCartItem is in the ticketscreen.xaml.cs:
private void removeCartItem(object sender, RoutedEventArgs e)
{
Console.WriteLine("TestingCartRemove");
}
Am I missing something obvious?
Thx in adv! :)
Edit:
There seems to be something infront of it... maybe the listbox? How do I make it so that I am not clicking the ListBox, but I can click on things within the Stackpanel, which are contents of the list box.
IsHitTestVisible="False" for the ListBox is disabling the click event for the Button. It makes all content within the ListBox invisible to hit-test as well.
Are you sure is not firing? Maybe you haven't seen the output in Visual Studio Output Window. Try to call a MessageBox.Show("Test"); instead.
You have a listbox control, which leads me to believe that this is not a console application. Therefore, Console.WriteLine() will not show you anything. Try MessageBox.Show() instead.
I have a WPF textBox that is declared as ReadOnly
<TextBox IsReadOnly="True" IsTabStop="False" Width="200" />
So, User can not write anything into the TextBox or delete the content but it still allows user to drag the text from this textbox and drop it in any other textbox that caused the text removed from the first textbox(the read-only one) and thats unexpected. Is it a bug?
how can I get rid of this?
I tried the following code :
<StackPanel>
<TextBox IsReadOnly="True">Hello</TextBox>
<TextBox></TextBox>
</StackPanel>
When I drag-and-drop the text (after selection) from the first TexbtBox to the second one, the text is copied, but not removed from the first TextBox. I tried it under .NET 3.5 and .NET 4.0 targets.
If you want to get rid of your bug without trying to understand it (since it shouldn't happen), you can just put an empty control (Canvas will be ok) on top of your TextBox, with its Background property set to transparent.
<Grid>
<TextBox IsReadOnly="True" IsTabStop="False" Width="200" />
<Canvas Background="Transparent"/>
</Grid>
But the text won't be selectable anymore...