Capturing name of StackPanel from Drop event - wpf

Within WPF I have the following XAML code:
<Page x:Class="com.MyCo.MyProj.Pages.Configuration.ManageLinkage.MasterLinkage"
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:local="clr-namespace:com.MyCo.MyProj.Pages.Configuration.ManageLinkage"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
Title="MasterLinkage">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="120"></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<TabControl TabStripPlacement="Top" Background="Transparent">
<TabItem Header="Import">
<ListBox Margin="0,5,0,0" Name="lbxImportItems" HorizontalAlignment="Left" VerticalAlignment="Top" Width="110" Background="Transparent"
PreviewMouseLeftButtonDown="lbxImportItems_PreviewMouseLeftButtonDown" >
<StackPanel Orientation="Vertical" HorizontalAlignment="Center" Name="DBImport">
<Image Source="/Images/DBImport25px.png" VerticalAlignment="Center" HorizontalAlignment="Center"></Image>
<TextBlock Text="Database" Foreground="AntiqueWhite"/>
</StackPanel>
<StackPanel Orientation="Vertical" Name="CSVImport">
<Image Source="/Images/CSVImport25px.png" VerticalAlignment="Center" HorizontalAlignment="Center"></Image>
<TextBlock Text="CSV Import" Foreground="AntiqueWhite"/>
</StackPanel>
</ListBox>
</TabItem>
</TabControl>
<Canvas x:Name="cnvsLinkScreen" AllowDrop="True" Grid.Column="1" Background="Transparent" Drop="cnvsLinkScreen_Drop" DragOver="cnvsLinkScreen_DragOver" ></Canvas>
</Grid>
The code for capturing the event is here:
private void cnvsLinkScreen_Drop(object sender, DragEventArgs e)
{
Canvas parent = (Canvas)sender;
object data = e.Data.GetData(typeof(string));
StackPanel objIn = (StackPanel)e.Data;
...
}
The drag and drop work great, the event method created the image in the canvas. However, I want to capture the Name="" from the StackPanels which are dropped.
I found the Name buried super deep in the "DragEventArgs e" object. I was think that there should be a way to cast the object (or the object within that object) as a StackPanel to easily work with it. The above code does not convert the StackPanel object( it's not at the root or the child object; I tried both) so it exceptions on "StackPanel objIn = (StackPanel)e.data;"
How do I either translate the incoming object to a StackPanel or how do I access the Name attribute from the Stackpanel?

I got it. I was close with the translation. To translate / typecast the object to what you are working with I needed to use the following line:
StackPanel objIn = (StackPanel)(e.Data.GetData(typeof(StackPanel)));
Which is slightly different than above.

Related

access codebehind method from resource dictionary in WPF

I have following grid inside WPF XML file
<Grid Grid.RowSpan="2" >
<Grid.ColumnDefinitions>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height = "Auto" />
</Grid.RowDefinitions >
<telerik:RadAutoCompleteBox TextSearchMode = "Contains" Grid.Column= "0" Grid.Row= "0" Name="cmbStyleNo" Margin= "5"
DisplayMemberPath="SAMPLE_ID" ItemsSource="{Binding Styles}"
SelectionMode= "Single" AutoCompleteMode= "Suggest" NoResultsContent= "No Matches" SelectionChanged= "val_SelectionChanged" />
</Grid >
above RadAutoCompleteBox SelectionChanged="val_SelectionChanged" code behind method exist in its code-behind file like follows
private void val_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
...
}
Then I have requirement populate above same grid in another window using resource dictionary. so I copied that grid to that ResourceDictionary like follows
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:samplePrjkt"
xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation">
<ToolBar x:Key="MyToolbar" Height="120">
<!--Template-->
<GroupBox Header="Template" Style="{StaticResource ToolbarGroup}" Margin="3">
<StackPanel Grid.Row="1" Orientation="Horizontal">
<StackPanel Orientation="Vertical" Margin="0,2,0,2">
<Grid Grid.RowSpan="2" >
<Grid.ColumnDefinitions>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<telerik:RadAutoCompleteBox TextSearchMode="Contains" Grid.Column="0" Grid.Row="0" Name="cmbStyleNo" Margin="5"
DisplayMemberPath="SAMPLE_ID" ItemsSource="{Binding Styles}"
SelectionMode="Single" AutoCompleteMode="Suggest" NoResultsContent="No Matches" SelectionChanged="val_SelectionChanged"/>
</Grid>
</StackPanel>
</StackPanel>
</GroupBox>
</ToolBar>
</ResourceDictionary>
then once I compile this I'm getting following error
'ResourceDictionary' root element requires a x:Class attribute to
support event handlers in the XAML file. Either remove the event
handler for the SelectionChanged event, or add a x:Class attribute to
the root element.
You need to manually add a code-behind file for the ResourceDictionary and define the val_SelectionChanged event handler in this file.
Please refer to the following link for more information and an example of how to do this:
Is it possible to set code behind a resource dictionary in WPF for event handling?
You basically just create a new class and name it "Dictionary1.xaml.cs" where "Dictionary1" is the name of your resource dictionary XAML file and then you set the x:Class attribute in the XAML file:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="WpfApplication1.Dictionary1"
...

Caliburn Micro Message.attach does not consider changes of datacontext

This is a simplified example. I have a usercontrol that contains a "browse to folder" functionality, using a textbox and a button. Clicking the button would open up the browse-dialog, and would essentially fill in the textbox.
<UserControl x:Class="MyUserControl"
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:cal="http://www.caliburnproject.org"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<!-- Folder -->
<TextBlock>Path</TextBlock>
<DockPanel LastChildFill="True" Grid.Column="1">
<Button DockPanel.Dock="Right" cal:Message.Attach="[Event Click] = [Action BrowseHotFolder()]" Content="..." HorizontalAlignment="Left" Width="25" Height="25" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" Margin="0,0,5,0"/>
<TextBox Text="{Binding HotFolderPath, UpdateSourceTrigger=PropertyChanged, ValidatesOnNotifyDataErrors=True}" />
</DockPanel>
</Grid>
I have a listbox that contains a number of objects. The selected object will be fed into this usercontrol as datacontext.
<Window>
...
<Listbox ItemsSource="{Binding Items, Mode=OneWay}" SelectedItem="{Binding SelectedItem}">
...
<view:MyUserControl DataContext="{Binding SelectedItem}" />
</Window>
Now, let's say I have two items in my listbox and I have the first one selected. I fill in "foo" in the textbox of MyUserControl. Then I select the second item, and fill in "bar". The databinding works fine, and both items have the correct values set. If I then click the browse button on the first one and select a folder, it will change the textbox of the first item to the selected path. However, if I select the second item, and browse to a folder it will ALSO change the first item's textbox.
My guess is that the message attach syntax does not call the browse action on the correct Item. It disregards the datacontext (currently selected item) and just uses the first one.
What can I do about this?
I think your guess is correct; the target used for the Message.Attach is the first data context bound, and does not update when the context is changed after the user selection.
We saw a similar problem with user controls switched in a content control - the fix was to specify cal:Action.TargetWithoutContext="{Binding}" on the button.
The issue is mentioned here by Rob Eisenberg:
https://caliburnmicro.codeplex.com/discussions/257005
I have made a workaround by changing
cal:Message.Attach="[Event Click] = [Action BrowseHotFolder()]"
to
cal:Message.Attach="[Event Click] = [Action BrowseHotFolder($datacontext)]"
Now, the BrowseHotFolder-method still is called on the wrong ItemViewModel, but weirdly $datacontext passes the correct ItemViewModel. In the method itself I now do:
public void BrowsePath(ItemViewModel context)
{
context.Path = _folderBrowsingService.Browse();
}
This is a workaround, but solves the problem.

Control blocking input to lower control

Hopefully this is a WPF issue and not a esri issue. I have an ESRI map control, and I am placing a control on top of the map. When I do this, the map no longer receives input(I can't move around or click anything). If I modify the z-index of the top control to place it behind the map, the map works fine again.
<Grid Name="MapGrid" DockPanel.Dock="Top" >
<Grid Name="MapGrid" DockPanel.Dock="Top" >
<esri:MapView x:Name="MainMapView" Panel.ZIndex="0" KeyDown="MyMapView_KeyDown" MapViewTapped="MyMapView_MapViewTapped" Map="{Binding Source={StaticResource MapResource}}" WrapAround="True" Grid.Row="0" Grid.Column="0" Initialized="MyMapView_Initialized" >
</esri:MapView>
<Expander Header="Properties" ExpandDirection="Right" Panel.ZIndex="-1">
<ItemsControl Background="Transparent" Height="700" Width="500" HorizontalAlignment="Left" VerticalAlignment="Top" Name="FeaturePropertyRegion" cal:RegionManager.RegionName="FeaturePropertyRegion" />
</Expander>
</Grid>
This code works, but if I raise the ZIndex of the Expander pannel, the map no longer receives input. I am assuming the issue has to do with the visual tree of WPF, and how input cascades down. Any ideas on what the issue could be? Thanks.
EDIT
The issue seems to be with the expander, as the map works if I remove the expander and just have the ItemsControl.
Try :
<Expander IsHitTestVisible="False">
<ItemsControl />
</Expander>
It doesn't seem to be a problem with extender, which would be very wired if it did
I tried this :
<Grid>
<Button />
<Expander HorizontalAlignment="Left" ExpandDirection="Right" VerticalAlignment="Top">
<Rectangle Fill="Red" Stretch="Fill" Width="525" Height="350"/>
</Expander>
</Grid>

Creating a sidebar - flyout like Windows desktop app in WPF

what i am trying to do is create a Desktop application in WPF whose UI is such that a small icon will remain fixed in the center of the left edge of screen and on click(or maybe hover) will slide open a sidebar(like the google desktop bar) running along the left edge of the screen (fixed position, cannot be moved).
do note that what i'm asking for might be like an appbar but i do not want the desktop icons along the left edge to be moved as it happens with an appbar i.e. i do not want it to hog up the desktop spacce....can anyone please suggest me a way out ??
I have implemented a partial solution using this, but i cant get the slide animation and fixed position to workout
Something like this could work:
then of course you could create a slide in animation for the sidebar. This shows (partial) transparency and the switching principle.
XAML:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
WindowStyle="None" Topmost="True" WindowState="Maximized"
AllowsTransparency="True" Background="Transparent">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Rectangle Name="rect" Width="100" VerticalAlignment="Stretch" Fill="#99000000" Visibility="Collapsed" />
<Button Style="{StaticResource {x:Static ToolBar.ButtonStyleKey}}" Width="32" Height="32" FontSize="16" VerticalAlignment="Center" HorizontalAlignment="Right" Background="White" Click="Button_Click">></Button>
</Grid>
</Window>
C#:
private void Button_Click(object sender, RoutedEventArgs e)
{
if (rect.Visibility == System.Windows.Visibility.Collapsed)
{
rect.Visibility = System.Windows.Visibility.Visible;
(sender as Button).Content = "<";
}
else
{
rect.Visibility = System.Windows.Visibility.Collapsed;
(sender as Button).Content = ">";
}
}
Based on this answer and more answers on this site I made a side bar, I liked the result so i made a repo.
https://github.com/beto-rodriguez/MaterialMenu
you can install it from nuget too.
here is an example
<materialMenu:SideMenu HorizontalAlignment="Left" x:Name="Menu"
MenuWidth="300"
Theme="Default"
State="Hidden">
<materialMenu:SideMenu.Menu>
<ScrollViewer VerticalScrollBarVisibility="Hidden">
<StackPanel Orientation="Vertical">
<Border Background="#337AB5">
<Grid Margin="10">
<TextBox Height="150" BorderThickness="0" Background="Transparent"
VerticalContentAlignment="Bottom" FontFamily="Calibri" FontSize="18"
Foreground="WhiteSmoke" FontWeight="Bold">Welcome</TextBox>
</Grid>
</Border>
<materialMenu:MenuButton Text="Administration"></materialMenu:MenuButton>
<materialMenu:MenuButton Text="Packing"></materialMenu:MenuButton>
<materialMenu:MenuButton Text="Logistics"></materialMenu:MenuButton>
</StackPanel>
</ScrollViewer>
</materialMenu:SideMenu.Menu>
</materialMenu:SideMenu>

Layout navigation window

I would like to build a WPF window application using the following layout structure. Consider title and button on left hand frame/window like "Master Pages" in ASP.Net. On the right hand frame it should be a WPF navigation window.
When I include Navigation Window as an UI element at the last stack panel, it throws me and error. How should I design the entire layout according to the image screenshot below? Thanks
<Window x:Class="MainWindow"
xmlns:local="clr-namespace:ClientSocket"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title=" Desktop" Height="841" Width="1271" WindowStartupLocation="CenterScreen" WindowState="Maximized">
<DockPanel>
<StackPanel DockPanel.Dock ="Top" Orientation="Horizontal" Background="Red">
<TextBlock Background="red" FontSize ="36" Width="482" >
Main Title
</TextBlock>
</StackPanel>
<StackPanel Background="LightGray" DockPanel.Dock ="Left" Width="145">
<Button Content="Button1" Name="btnAndroid" Width="119" Margin="3" BorderBrush="{StaticResource {x:Static SystemColors.InfoBrushKey}}" />
<Button Content="Button2" Name="btnDownloads" Width="119" Margin="3" BorderBrush="{StaticResource {x:Static SystemColors.InfoBrushKey}}" />
<Button Content="AddNewDownloads" Height="37" Name="Button1" Width="133" />
</StackPanel>
<StackPanel>
<NavigationWindow Height="auto" Width="auto" Name="nwMain" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" BorderBrush="Blue" BorderThickness="1" />
</StackPanel>
</DockPanel>
</Window>
You cannot add a window as the child of anything, there is a nestable navigation control which you can use here instead, it is called Frame.
Layout-wise i would recommend a Grid with two rows, contains another Grid (in Grid.Row="1") with two columns.
DockPanels are sad controls that probably should not be used, unless someone points a gun at you and tells you to.

Resources