I need help accessing in C# a TreeView created in .xaml.
I'm creating a simple TreeView that will collect all "Layers" from a document, and populate the TreeView with their names and other properties.
As a start point, I just want the names, then I'll add more properties.
The .xaml is as follows:
<Window x:Class="TestWPFAlpha.DocumentStructureWindow"
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:TestAlpha"
mc:Ignorable="d"
Closing="Window_Closing"
Title=" Document Structure" Height="600" MinHeight="600" MaxHeight="600" Width="400" MinWidth="400" MaxWidth="400" ScrollViewer.VerticalScrollBarVisibility="Visible">
<Grid x:Name="gridDocumentStructure" x:FieldModifier="public">
<Menu Height="25" Margin="0,0,0,0" VerticalAlignment="Top" FontSize="14" Background="#FF3C4B64" Foreground="White">
<MenuItem Header="Search" />
<MenuItem Header="Close" Height="25" Click="buttonCloseDocumentStructureWindow_Click"/>
</Menu>
<TreeView x:Name="TreeViewDocumentStructure" x:FieldModifier= "public" Background="#FFEBEBEB" Margin="10,35,10,10">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Members}">
<TextBlock Text="{Binding Name}"/>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</Grid>
</Window>
In C# I have:
// all necessary using statements and the two below, that are specific thar I need in this method
using static TestWPFAlpha.DocumentStructureWindow;
using static DocumentLayers.LayerManagerWindow;
...
and an event for a button as below:
public static void DocumentStructure_Click(object sender, RoutedEventArgs e)
{
if (documentStructureWindow == null)
{
documentStructureWindow = new TestWPFAlpha.DocumentStructureWindow();
documentStructureWindow.Show();
}
else
{
documentStructureWindow.Activate();
}
var tds = new TestWPFAlpha.DocumentStructureWindow.gridDocumentStructure.TreeViewDocumentStructure();
System.Type canvasType = typeof(System.Windows.Controls.Canvas);
int count = 0;
foreach (UIElement uie in TestWPFAlpha.MainWindow.canvasGrid.Children)
{
if (uie.GetType() == canvasType && count > 0)
{
sb.AppendLine(Layers[count - 1].Name);
TreeViewItem newChild = new TreeViewItem();
// Layers are from DocumentLayers.LayerManagerWindow
newChild.Header = Layers[count - 1].Name;
tds.Items.Add(newChild);
}
count++;
}
}
At line 49
var tds = new TestWPFAlpha.DocumentStructureWindow.gridDocumentStructure.TreeViewDocumentStructure();
I get the error:
The type name 'gridDocumentStructure' does not exist in the type 'DocumentStructureWindow'
Help greatly appreciated.
An example as you requested. It's just a basic thing using code behind
the window with the tree view:
<Window x:Class="TestWPFAlpha.DocumentStructureWindow"
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:TestWPFAlpha"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid x:Name="gridDocumentStructure" x:FieldModifier="public">
<Menu Height="25" Margin="0,0,0,0" VerticalAlignment="Top" FontSize="14" Background="#FF3C4B64" Foreground="White">
<MenuItem Header="Search" />
<MenuItem Header="Close" Height="25" Click="buttonCloseDocumentStructureWindow_Click"/>
</Menu>
<TreeView x:Name="TreeViewDocumentStructure" x:FieldModifier= "public" Background="#FFEBEBEB" Margin="10,35,10,10">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Members}">
<TextBlock Text="{Binding Name}"/>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</Grid>
it creates a new window:
usings...;
namespace TestWPFAlpha
{
public partial class DocumentStructureWindow : Window
{
public DocumentStructureWindow()
{
InitializeComponent();
var newWin = new Window1(this);
newWin.Show();
}
}
}
and the newWin has a button, which does what I think you would like to achieve:
public partial class Window1 : Window
{
private DocumentStructureWindow _documentStructureWindow;
public Window1(DocumentStructureWindow documentStructureWindow)
{
InitializeComponent();
_documentStructureWindow = documentStructureWindow;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
var tds = _documentStructureWindow.TreeViewDocumentStructure;
tds.Items.Add(new TreeViewItem() { Header = DateTime.Now.ToString("yyMMdd_HHmmss_fff")} );
}
}
see it here: repo
But I would recommend mvvm & commands instead of this code behind solution
Related
I am trying to dynamically create DataGrids in WPF, one below the other in a Grid. the problem is that I don't even know where to start, I saw that it could be done through code but I would like to use XAML correctly.
void PopulateDatagridSQL(string Data, string index, string TabName)
{
try
{
Data = Data.Replace((Char)6, (Char)124);
List<DataTable> Results = new List<DataTable>();
Results = JsonConvert.DeserializeObject<List<DataTable>>(Data);
foreach (SQLWindow SingleSQLWindows in StaticVar.MySQLWindows)
{
if (SingleSQLWindows.MyINDEX == index)
{
SingleSQLWindows.Dispatcher.Invoke(new Action(() =>
{
foreach (TabItem item in SingleSQLWindows._tabItems)
{
if (item.Name == TabName)
{
//create multiple datagrids up to results.count
((SQLPage)((Frame)item.Content).Content).DataGrid1.ItemsSource = Results[0].DefaultView;//foreach
((SQLPage)((Frame)item.Content).Content).TxtSqlLog.Text = "Records in Datagrid: " + Results[0].Rows.Count;//foreach
}
}
}));
}
}
}
catch (Exception asd)
{
foreach (SQLWindow SingleSQLWindows in StaticVar.MySQLWindows)
{
if (SingleSQLWindows.MyINDEX == index)
{
SingleSQLWindows.Dispatcher.Invoke(new Action(() =>
{
foreach (TabItem item in SingleSQLWindows._tabItems)
{
if (item.Name == TabName)
{
((SQLPage)((Frame)item.Content).Content).TxtSqlLog.Text = "Error in $SqlResponse";
}
}
}));
}
}
}
}
In this function I receive a list of DataTables and for each DataTable I have to create a DataGrid.
<Page x:Class="Emergency_APP_Server_WPF.Forms.SQLPage"
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:Emergency_APP_Server_WPF.Forms"
mc:Ignorable="d" x:Name="SQLPageXaml" Loaded="SQLPage_Loaded"
d:DesignHeight="450" d:DesignWidth="800"
Title="SQLPage" >
<Grid>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" MinHeight="100"></RowDefinition>
<RowDefinition Height="0"></RowDefinition>
<RowDefinition Height="*" MinHeight="150"></RowDefinition>
<RowDefinition Height="35"></RowDefinition>
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition Width="70"></ColumnDefinition>
</Grid.ColumnDefinitions>
<avalonEdit:TextEditor Grid.Column="0" Background="White"
xmlns:avalonEdit="http://icsharpcode.net/sharpdevelop/avalonedit"
Name="MyAvalonEdit" FontFamily="Consolas"
FontSize="11pt" Margin="10,10,10,10" ShowLineNumbers="True"
LineNumbersForeground="Gray" ScrollViewer.VerticalScrollBarVisibility="Auto"
ScrollViewer.HorizontalScrollBarVisibility="Auto" KeyUp="MyAvalonEdit_KeyUp"/>
<Button Grid.Column="1" x:Name="BtnSendSQL" Margin="0,10,10,10" Click="BtnSendSQL_Click">
<StackPanel>
<Image Height="25" Source="..//Resources/send.png"></Image>
<TextBlock Margin="0,10,0,0" VerticalAlignment="Top" Foreground="White" Text="SendSQL"></TextBlock>
</StackPanel>
</Button>
</Grid>
<GridSplitter Margin="0,-10,0,0" Grid.Row="1" HorizontalAlignment="Stretch" Background="Transparent" ResizeBehavior="PreviousAndNext">
</GridSplitter>
<DataGrid Grid.Row="2" x:Name="DataGrid1" RowStyle="{StaticResource DataGridRowSql}" Style="{StaticResource DataGridStyleSQL}" >
<DataGrid.CommandBindings>
<CommandBinding Command="Copy" Executed="CommandBinding_Executed"></CommandBinding>
</DataGrid.CommandBindings>
<DataGrid.InputBindings>
<KeyBinding Key="C" Modifiers="Ctrl" Command="Copy"></KeyBinding>
</DataGrid.InputBindings>
</DataGrid>
<TextBlock TextAlignment="Center" TextWrapping="Wrap" VerticalAlignment="Bottom" Grid.Row="3" x:Name="TxtSqlLog" Text="Wait For Commands..."
FontSize="14" FontFamily="Consolas" Foreground="White"></TextBlock>
</Grid>
</Grid>
I do not know the exact layout where you want to put all the DataGrids, so I just assume you want to place them in row 2 of your Grid. As you want to stack them, you can use an ItemsControl in a ScrollViewer. The latter is just there, so you can scroll through the DataGrids in case the page is too small to display them all. So this is the basic layout for the solutions below.
<Grid>
<Grid.RowDefinitions>
<!-- ...your row definitions. -->
</Grid.RowDefinitions>
<!-- ...your other controls. -->
<ScrollViewer Grid.Row="2">
<ItemsControl/>
</ScrollViewer>
</Grid>
Code-behind solution
In code-behind, you need to access the ItemsControl, so assign it a name.
<ItemsControl x:Name="DataGridContainer"/>
Then just create DataGrids in a loop from your DataTable list.
foreach (var dataTable in Results)
{
var dataGrid = new DataGrid { ItemsSource = dataTable.DefaultView };
DataGridContainer.Items.Add(dataGrid);
};
By the way, in this scenario, you could also use a StackPanel instead of an ItemsControl.
MVVM solution
You can create a property in your view model that exposes the default views of your DataTables.
public ObservableCollection<DataView> DataViews { get; }
Make sure you instantiate the collection in the constructor or implement INotifyPropertyChanged, so that the collection is available in XAML. Then bind the ItemsControl to this collection.
<ItemsControl ItemsSource="{Binding DataViews}"/>
Next create a DataTemplate for the DataView type. As each data view in the bound collection represents a data table that should be displayed as a DataGrid, it would look like this.
<DataTemplate DataType="{x:Type data:DataView}">
<DataGrid ItemsSource="{Binding}"/>
</DataTemplate>
Then you have to assign this data template as ItemTemplate in the ItemsControl. I just inline it here, but you can also put it in any ResourceDictionary and reference it via StaticResource.
<ItemsControl ItemsSource="{Binding DataViews}">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type data:DataView}">
<DataGrid ItemsSource="{Binding}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Now, you just have to add the default views to the DataViews collection. As this collection is an ObservableCollection, it will notify the ItemsControl to update on each add.
foreach (var dataTable in Results)
{
DataViews.Add(dataTable.DefaultView);
};
As an item is added, the ItemsControl will get notified and creates an item using the DataTemplate.
I recommend you to use the MVVM solution, as it separates the presentation from your data and is much easier to realize and customization of the DataGrids via the DataTemplate is much easier, convenient and maintainable in XAML.
<Page x:Class="Emergency_APP_Server_WPF.Forms.SQLPage"
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:z="clr-namespace:System.Data;assembly=System.Data"
xmlns:local="clr-namespace:Emergency_APP_Server_WPF.Forms"
mc:Ignorable="d" x:Name="SQLPageXaml" Loaded="SQLPage_Loaded"
d:DesignHeight="450" d:DesignWidth="800"
Title="SQLPage" >
<Grid>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" MinHeight="100"></RowDefinition>
<RowDefinition Height="0"></RowDefinition>
<RowDefinition Height="*" MinHeight="150"></RowDefinition>
<RowDefinition Height="35"></RowDefinition>
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition Width="70"></ColumnDefinition>
</Grid.ColumnDefinitions>
<avalonEdit:TextEditor Grid.Column="0" Background="White"
xmlns:avalonEdit="http://icsharpcode.net/sharpdevelop/avalonedit"
Name="MyAvalonEdit" FontFamily="Consolas"
FontSize="11pt" Margin="10,10,10,10" ShowLineNumbers="True"
LineNumbersForeground="Gray" ScrollViewer.VerticalScrollBarVisibility="Auto"
ScrollViewer.HorizontalScrollBarVisibility="Auto" KeyUp="MyAvalonEdit_KeyUp"/>
<Button Grid.Column="1" x:Name="BtnSendSQL" Margin="0,10,10,10" Click="BtnSendSQL_Click">
<StackPanel>
<Image Height="25" Source="..//Resources/send.png"></Image>
<TextBlock Margin="0,10,0,0" VerticalAlignment="Top" Foreground="White" Text="SendSQL"></TextBlock>
</StackPanel>
</Button>
</Grid>
<GridSplitter Margin="0,-10,0,0" Grid.Row="1" HorizontalAlignment="Stretch" Background="Transparent" ResizeBehavior="PreviousAndNext">
</GridSplitter>
<ScrollViewer Grid.Row="2">
<ItemsControl ItemsSource="{Binding DataViews}">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type z:DataView}">
<DataGrid RowStyle="{StaticResource DataGridRowSql}" Style="{StaticResource DataGridStyleSQL}" ItemsSource="{Binding}">
<DataGrid.CommandBindings>
<CommandBinding Command="Copy" Executed="CommandBinding_Executed"></CommandBinding>
</DataGrid.CommandBindings>
<DataGrid.InputBindings>
<KeyBinding Key="C" Modifiers="Ctrl" Command="Copy"></KeyBinding>
</DataGrid.InputBindings>
</DataGrid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
<TextBlock TextAlignment="Center" TextWrapping="Wrap" VerticalAlignment="Bottom" Grid.Row="3" x:Name="TxtSqlLog" Text="Wait For Commands..."
FontSize="14" FontFamily="Consolas" Foreground="White"></TextBlock>
</Grid>
</Grid>
public ObservableCollection<DataView> _DataViews = new ObservableCollection<DataView>();
public ObservableCollection<DataView> DataViews
{
get
{
return _DataViews;
}
set
{
_DataViews = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string Param = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(Param));
}
foreach (SQLWindow SingleSQLWindows in StaticVar.MySQLWindows)
{
if (SingleSQLWindows.MyINDEX == index)
{
SingleSQLWindows.Dispatcher.Invoke(new Action(() =>
{
foreach (TabItem item in SingleSQLWindows._tabItems)
{
if (item.Name == TabName)
{
foreach (DataTable itemTable in Results)
{
//SingleSQLWindows.DataViews.Add(itemTable.DefaultView);
////create more datagrid while results.count
///
((SQLPage)((Frame)item.Content).Content).DataViews.Add(itemTable.DefaultView);
//((SQLPage)((Frame)item.Content).Content).TxtSqlLog.Text = "Records in Datagrid: " + Results[0].Rows.Count;//foreach
}
}
}
}));
}
}
the visual studio does not report any errors but the scrollviewer remains empty, I cannot understand why
I Work with the theme of MahApps (Metro Dark) I looked the animations of this theme.
I came to a dead end: indeed I created a system to switch between different UserControl, that is to say that I have only one window and clicking on different buttons, I have this or such UserControl. But now I am with this system switch, I have no animation (only the start of the application).
How can I make an animation for each change in UserControl (Keeping Metro theme)?
Somebody ask me : use TransitioningContentControl
But i made my switcher like this :
class Switcher
{
public static UserControl WClient;
public static UserControl WHome;
public static UserControl WDataBase;
public Switcher()
{
WClient = new Windows.Client();
WHome = new Windows.Home();
WDataBase = new Windows.DataBase();
}
public static void currentWindow(UserControl window, string color)
{
Window curApp = Application.Current.MainWindow;
curApp.Content = window;
if (window == WClient)
{
curApp.Title = "CLIENT - INFO-TOOLS - BY NAOGRAFIX";
}
else if (window == WDataBase)
{
curApp.Title = "DATABASE - INFO-TOOLS - BY NAOGRAFIX";
}
else
{
curApp.Title = "HOME - INFO-TOOLS - BY NAOGRAFIX";
}
currentColor(color);
}
}
Now, when i clic on a button (to switch userControl) i use this :
private void BtnDataBase_Click(object sender, RoutedEventArgs e)
{
var color = "Red";
if (DataBase.isConnected) { color = "Green"; }
Switcher.currentWindow(Switcher.WDataBase, color);
}
I use CONTENT, i dont know if i can use TransitioningContentControl
Help :)
Nao*
You do need to use transitioning content control as you have said. You can add that as the direct content of the window then access it by name from the mainwindow and change its content instead.
Xaml
<metro:TransitioningContentControl x:Name="tContent"/>
C#
((ContentControl)curApp.FindName("tContent")).Content = window;
You will need the xml namespace definition
xmlns:metro="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
and you can change the transition using the Transition property on TransitioningContentControl
WPF XAML below shows use of MahApps.Metro TransitioningContentControl.
Click on the Content listbox to switch content.
Select the transition effect in the Transition listbox, then change selected Content to see the effect.
<Window x:Class="WpfMahApp.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:mah="http://metro.mahapps.com/winfx/xaml/controls"
mc:Ignorable="d"
Title="MainWindow" Height="600" Width="800">
<Window.Resources>
<TextBlock x:Key="Content1" Width="400" Height="200" Text="Content 1: TextBox" Background="Aqua" />
<Canvas x:Key="Content2" Width="200" Height="400" Background="DarkOrange">
<Ellipse Fill="YellowGreen" Stroke="Black" Width="100" Height="200" />
<Label Content="Content2: Canvas" />
</Canvas>
<Border x:Key="Content3" Width="100" Height="100" Background="Yellow" BorderBrush="Blue" BorderThickness="2" CornerRadius="4">
<TextBlock Text="Content3: Border" />
</Border>
</Window.Resources>
<StackPanel Orientation="Horizontal">
<StackPanel Orientation="Vertical" >
<CheckBox Margin="4" Content="Is Transitioning" IsChecked="{Binding ElementName=TransitioningContentControl,Path=IsTransitioning , Mode=OneWay}" />
<StackPanel Orientation="Vertical" Margin="8">
<TextBlock Text="Content" FontWeight="Bold"/>
<ListBox Name="ContentSelection" HorizontalAlignment="Left">
<ListBoxItem Content="Content 1" Tag="{StaticResource Content1}" />
<ListBoxItem Content="Content 2" Tag="{StaticResource Content2}" />
<ListBoxItem Content="Content 3" Tag="{StaticResource Content3}" />
</ListBox>
</StackPanel>
<StackPanel Orientation="Vertical" Margin="8">
<TextBlock Text="Transition" FontWeight="Bold" />
<ListBox Name="Transition" HorizontalAlignment="Left">
<ListBoxItem Content="Default" Tag="{x:Static mah:TransitionType.Default}"/>
<ListBoxItem Content="Normal" Tag="{x:Static mah:TransitionType.Normal}"/>
<ListBoxItem Content="Up" Tag="{x:Static mah:TransitionType.Up}"/>
<ListBoxItem Content="Down" Tag="{x:Static mah:TransitionType.Down}"/>
<ListBoxItem Content="Left" Tag="{x:Static mah:TransitionType.Left}" />
<ListBoxItem Content="Right" Tag="{x:Static mah:TransitionType.Right}"/>
<ListBoxItem Content="LeftReplace" Tag="{x:Static mah:TransitionType.LeftReplace}"/>
<ListBoxItem Content="RightReplace" Tag="{x:Static mah:TransitionType.RightReplace}"/>
</ListBox>
</StackPanel>
</StackPanel>
<mah:TransitioningContentControl Margin="8"
Name="TransitioningContentControl"
Background="Beige" BorderBrush="Black" BorderThickness="1"
Content="{Binding ElementName=ContentSelection, Path=SelectedValue.Tag}"
Transition="{Binding ElementName=Transition, Path=SelectedValue.Tag}" />
</StackPanel>
</Window>
thats my navigation window
<NavigationWindow x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="800" Width="600" Source="Page1.xaml">
thats my page1
<Page x:Class="WpfApplication1.Page1"
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="600" d:DesignWidth="800"
Title="Page1" Name="IndexPage">
<ListView Name="myListView" ItemsSource="{Binding ElementName=IndexPage, Path=SeriesCollection}" ScrollViewer.HorizontalScrollBarVisibility="Disabled" IsSynchronizedWithCurrentItem="True" SelectionChanged="handleSelected">
<ListView.ItemsPanel >
<ItemsPanelTemplate>
<WrapPanel>
</WrapPanel>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel >
<Image Width="214" Height="317" Source="{Binding Image}"/>
<Label Content="{Binding Name}" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Page 2 is just en empty skeleton
code behind
namespace WpfApplication1
{
/// <summary>
/// Interaktionslogik für Page1.xaml
/// </summary>
public partial class Page1 : Page
{
private ObservableCollection<Series> _series =
new ObservableCollection<Series>();
public ObservableCollection<Series> SeriesCollection
{
get { return _series; }
}
public Page1()
{
InitializeComponent();
DirectoryInfo baseDir = new DirectoryInfo(#"C:\Serien");
DirectoryInfo[] dirs = baseDir.GetDirectories();
foreach (DirectoryInfo dir in dirs)
{
Series serie = new Series(dir);
Console.WriteLine("adding " + serie.Name);
_series.Add(serie);
}
Console.WriteLine(_series.Count);
}
public void handleSelected(object sender, RoutedEventArgs args)
{
Series currentSerie = (Series) myListView.Items.CurrentItem;
Page2 page = new Page2();
this.NavigationService.Navigate(page);
Console.WriteLine(currentSerie.Name);
Console.WriteLine(currentSerie.GetType());
Console.WriteLine(currentSerie.ToString());
}
}
}
so i click on an item to trigger the SelectionChanged Event to handle it in SelectionChanged where i navigate to page2 , so far so good.
then i use the back button from the navigation window and get stuck with an NullpointerException at
this.NavigationService.Navigate(page);
i dont even know why this method is triggered. So obviosly i am doing something stupid. Pls tell me what it is. Thanks for your time and affort.
The problem here is that you handle the wrong event. I assume that you want to open Page2 by clicking a ListViewItem. Therefore you should use mouse events instead of SelectionChanged.
For example, you can subscribe to StackPanel MouseDown event in your DataTemplate:
<DataTemplate>
<StackPanel Background="Transparent"
MouseDown="StackPanel_MouseDown">
<Image Width="214" Height="317" Source="{Binding Image}"/>
<Label Content="{Binding Name}"/>
</StackPanel>
</DataTemplate>
You can access clicked Series using the following:
private void StackPanel_MouseDown(object sender, MouseButtonEventArgs e)
{
var currentSerie = (Series)((StackPanel)sender).DataContext;
...
}
UPD If you need a real click, you may use a trick like this:
<DataTemplate>
<Button Click="Button_Click">
<Button.Template>
<ControlTemplate TargetType="Button">
<ContentPresenter/>
</ControlTemplate>
</Button.Template>
<StackPanel Background="Transparent">
<Image Width="214" Height="317" Source="{Binding Image}"/>
<Label Content="{Binding Name}"/>
</StackPanel>
</Button>
</DataTemplate>
We use a Button like a view-model which is able to handle clicks.
I have this data grid where I am placing all my buttons
<Grid x:Name="ButtonGrid" HorizontalAlignment="Left" Margin="0,90,0,4" Width="186">
<Button x:Name="B1" Content="B1" Height="18" Margin="73,0,59,16" VerticalAlignment="Bottom" Click="B1"/>
<Button x:Name="B2" Content="B2" Height="18" Margin="0,0,-2,16" VerticalAlignment="Bottom" Click="B2_Click" HorizontalAlignment="Right" Width="57"/>
</Grid>
I have the grid collapased on start. But when a button {testGrid} is clicked, I want the grid to ne visible.
Here is my code
namespace project.Test
{
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
}
EDUTED
private void testGrid_Click(object sender, System.Windows.RoutedEventArgs e)
{
FrameworkElement ButtonGrid = (sender as FrameworkElement).FindName("ButtonGrid") as FrameworkElement;
if ( ButtonGrid.Visibility == System.Windows.Visibility.Collapsed)
ButtonGrid.Visibility = System.Windows.Visibility.Visible;
else
ButtonGrid.Visibility = System.Windows.Visibility.Collapsed;
}
}
}
I think if you move your Grid outside of your DataTemplate it will work. :)
However if you really need to put it in a DataTemplate, as long as your Button is at the same level as the Grid, you should still be able to find it.
Say your xaml code looks like this,
<UserControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="controlstoryboardactionrefissue.MainPage" Width="640" Height="480">
<UserControl.Resources>
<DataTemplate x:Key="DataTemplate1">
<Grid x:Name="myGrid" Height="128" Background="#FFE7C0C0" Width="333">
<Button x:Name="myButton" Content="Button" HorizontalAlignment="Left" VerticalAlignment="Top" Width="75" Margin="31,29,0,0" Click="myButton_Click" />
</Grid>
</DataTemplate>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" Background="White">
<ContentControl HorizontalAlignment="Left" VerticalAlignment="Top" Margin="175,198,0,0" ContentTemplate="{StaticResource DataTemplate1}" />
</Grid>
</UserControl>
Then the code behind,
private void myButton_Click(object sender, System.Windows.RoutedEventArgs e)
{
var myButton = (Button)sender;
var grid = myButton.Parent as Grid;
if (grid != null)
{
// do stuff
}
}
Hope it helps. :)
I'm doing some drag and drop between two ListBox items containing a UserControl, ClaimSectionTemplate as the DataTemplate for the items in the collection that are populating the source listbox.
Now I have 2 buttons on ClaimSectionTemplate, AddField and RemoveField, and they respectively add and remove fields from a child collection on the ClaimSection object that is shown in the ClaimSectionTemplate user control.
So what is happening is when I drop a ClaimSection into the target ListBox the original object becomes unresponsive no longer allowing me to interact with the user control.
MainWindow.Xaml
<ListBox Margin="13,12,12,12" Name="NewSections" Grid.Column="1" AllowDrop="True" Drop="NewSections_Drop">
<ListBox.ItemTemplate>
<DataTemplate>
<me:ClaimSectionTemplate />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Window>
Main Window Drag Drop Handlers
private void ExistingSections_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
var parent = (ListBox)sender;
dragSource = parent;
var data = ExistingSections.SelectedItem;
if (data != null)
{
DragDrop.DoDragDrop(parent, data, DragDropEffects.Move);
}
}
private void NewSections_Drop(object sender, DragEventArgs e)
{
Models.ClaimSection dropData = (Models.ClaimSection)e.Data.GetData(typeof(Models.ClaimSection));
ClaimSectionsNew.addClaimSection(dropData);
ClaimSectionsExisting.removeClaimSection(dropData);
}
ClaimSectionTemplate.xaml
<UserControl x:Class="InsuranceBuildVer1.Views.ClaimSectionTemplate"
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="187" d:DesignWidth="300">
<Grid Height="185">
<TextBlock Height="23" Margin="12,12,12,0" Name="textBlock1" Text="{Binding Path=ClaimType}" VerticalAlignment="Top" />
<ListBox x:Name="FieldList" HorizontalAlignment="Left" Margin="10,71,0,12" Width="278" ItemsSource="{Binding Path=Fields.ClaimFields, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBox Text="{Binding Path=Identifier}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Button Content="Add Field" Height="23" HorizontalAlignment="Left" Margin="12,42,0,0" Name="AddField" VerticalAlignment="Top" Width="75" Click="AddField_Click" />
<Button Content="Remove Field" Height="23" HorizontalAlignment="Left" Margin="103,42,0,0" Name="RemoveField" VerticalAlignment="Top" Width="96" Click="RemoveField_Click" />
</Grid>
</UserControl>