WPF populate treeview selection into a textbox - wpf

Any help is appreciated. I'm very new to WPF. I have a treeview that is being populated by an xml file. When the treeview item is selected, I need it to show up in a text box. I have the treeview inside a popup and I've got it so that when the textbox in question is selected, it will bring up the popup with treeview prompting the user to make a selection on the treeview. Afterwards it should put that treeview selection back into the same textbox. Here's my code:
<TextBox Name="text"
Text="{Binding Path=SelectedItem.name, ElementName=dirTree}"
Style="{StaticResource CustomTextBoxStyle}"
Grid.Column="1"
Margin="47,326,110,140"
TextChanged="text_TextChanged" />
And the treeview portion:
<Popup PlacementTarget="{Binding ElementName=text}"
VerticalOffset="20"
HorizontalOffset="-180"
Margin="0,0,465,279"
Name="popup1"
AllowsTransparency="True"
Placement="Top">
<Popup.Style>
<Style TargetType="{x:Type Popup}">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=text, Path=IsFocused}"
Value="True">
<Setter Property="IsOpen"
Value="True" />
</DataTrigger>
<!--<DataTrigger Binding="{Binding ElementName=popupText, Path=IsFocused}"
Value="True">
<Setter Property="IsOpen"
Value="True" />
</DataTrigger>-->
</Style.Triggers>
</Style>
</Popup.Style>
<Grid>
<Border BorderThickness="2"
Background="DodgerBlue"
BorderBrush="DodgerBlue"
Padding="0"
CornerRadius="6">
<ScrollViewer Height="300"
Name="scrollViewer1"
Width="175"
BorderBrush="Black"
Background="DodgerBlue">
<TreeView Name="dirTree"
ItemsSource="{Binding Source={StaticResource xmldata}, XPath=.}"
VirtualizingStackPanel.IsVirtualizing="False"
VirtualizingStackPanel.VirtualizationMode="Standard"
GotFocus="TreeView1_GotFocus"
SelectedItemChanged="{Binding ElementName=dirTree, Path=SelectedItem}"/>
</ScrollViewer>
</Border>
</Grid>
</Popup>

Create an event handler on the SelectedItemChanged event from your TreeView and from there, update your TextBlock.Text.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TreeView x:Name="demoTreeView"
Margin="10"
SelectedItemChanged="demoTreeView_SelectedItemChanged">
</TreeView>
<TextBlock x:Name="demoTextBox" Grid.Row="1"/>
</Grid>
And in the .cs file :
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
demoTreeView.Items.Add("test1");
demoTreeView.Items.Add("test2");
demoTreeView.Items.Add("test3");
demoTreeView.Items.Add("test4");
}
private void demoTreeView_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
{
demoTextBox.Text = e.NewValue.ToString();
}
}
Personalty I would recommend you to use MVVM and bindings on Properties in order to have a nice decoupling between the xaml and the code-behind.

Related

Swiching the Stackpanel in single ViewModel Using Back/Next Button WPF

I have a WPF, with Form with multiple user required questions. I have created 2 Stackpanels which have similar layout, first form (Stackpanel) will let the user to fill up information.While second form (Stackpanel) would be preview form for the user before he submits.
XAML Code
<Window x:Class="NinjaLIB.View.SSOEMWarrantyButtonExtension"
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:NinjaLIB.View"
xmlns:lex="http://wpflocalizeextension.codeplex.com"
lex:LocalizeDictionary.DesignCulture="en"
lex:ResxLocalizationProvider.DefaultAssembly="NinjaLIB"
lex:ResxLocalizationProvider.DefaultDictionary="Resources"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
DataContext="{Binding Path=RMAView, Source={StaticResource Locator}}"
mc:Ignorable="d"
Title="Request RMA" Height="600" Width="1000"
xmlns:mvvmlight="http://www.galasoft.ch/mvvmlight"
xmlns:converter="clr-namespace:NinjaLIB.Converter"
WindowStartupLocation="CenterScreen" ResizeMode="NoResize">
<i:Interaction.Triggers>
<!--<i:EventTrigger EventName="Closed">
<mvvmlight:EventToCommand Command="{Binding GetRMAWindowClosed}" PassEventArgsToCommand="True" />
</i:EventTrigger>-->
<!--<i:EventTrigger EventName="Loaded">
<mvvmlight:EventToCommand Command="{Binding GetWarrantyWindowLoaded}" PassEventArgsToCommand="True" />
</i:EventTrigger>-->
</i:Interaction.Triggers>
<Grid Margin="10">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!--Some QUestions asked to the User-->
<Grid Grid.Row="2">
<!--View Form Fill-->
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<StackPanel Orientation="Vertical">
<StackPanel.Style>
<Style TargetType="StackPanel">
<Setter Property="Visibility" Value="Visible"/>
<Style.Triggers>
<DataTrigger Binding="{Binding ViewState}" Value="FormFillViewState">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</StackPanel.Style>
**<!--Some QUestions asked to the User-->**
</StackPanel >
</ScrollViewer>
**<!--View Preview Form-->**
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<StackPanel>
<StackPanel.Style>
<Style TargetType="StackPanel">
<Setter Property="Visibility" Value="Collapsed"/>
<Style.Triggers>
<DataTrigger Binding="{Binding ViewState}" Value = "PreviewFillState" >
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</StackPanel.Style>
**<!--Some QUestions asked to the User-->**
</StackPanel>
</ScrollViewer>
</Grid>
<Grid Grid.Row="3">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!--Buttons-->
<Button Grid.Row="0" Content="Next"
IsEnabled="{Binding IsConnected}"
Command="{Binding NextCommandBtn}"
FontWeight="Normal"
HorizontalContentAlignment="Center"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Height="30"
Width="80"
Margin="780,0,0,2"
Padding="3,0"/>
<Button Grid.Row="0" Content="Back"
IsEnabled="{Binding IsConnected}"
Command="{Binding BackCommandBtn}"
FontWeight="Normal"
HorizontalContentAlignment="Center"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Height="30"
Width="80"
Margin="420,0,0,2"
Padding="3,0"/>
</Window>
==============
View Model Section Code
==============
private RMAViewModel RMAView;
private readonly ResourceManager rm;
public RMAViewModel()
{
rm = new ResourceManager("NinjaLIB.Properties.Resources", Assembly.GetExecutingAssembly());
}
//Properties for the Window (Date and Text) for FormFillViewState
//Properties for the Window (Date and Text) for PreviewFillState
==============
I wanted some help with view Model code, where if I click NextCommandBtn all the data will appear as filled up form from first stackpanel view and when I select BackCommandBtn i can edit the form.
You can think about it like this:
You have two views (StackPanels) and only one can be displayed at a time.
So in your view-model, you need a property that tells you which view is active. A simple bool property for each view would work. Since there are only two views, you could technically just use a single property, but using two will make your XAML data binding a little easier.
Examples:
IsFormActive
IsPreviewActive
In your XAML, you need to control the Visibility property of your two StackPanel controls based on your IsFormActive and IsPreviewActive properties in your view-model. You can do this with a value converter, specifically the BooleanToVisibilityConverter.
<StackPanel Visibility="{Binding IsFormActive,
Converter={StaticResource BooleanToVisibilityConverter}">
...
</StackPanel>
<StackPanel Visibility="{Binding IsPreviewActive,
Converter={StaticResource BooleanToVisibilityConverter}">
...
</StackPanel>
And back in your view-model you can control the state of IsFormActive and IsPreviewActive when the next and back buttons are clicked, etc.
I hope this helps you get an idea of how to proceed.

How to avoid selecting DataGridRow in ParentDataGrid by Clicking in DataGridDetailsPresenter?

I have a DataGrid (ParentDataGrid) with a DataGridDetailsPresenter. In the DataGridDetailsPresenter I have another DataGrid (ChildDataGrid). If I select a Row in the ChildDataGrid the surrounding DataGridRow of the ParentDataGrid is selected too.
I get that both the ParentDataGrid and the ChildDataGrid throws the SelectionChanged event. I tried to deselect selection in ParentDataGrid. But then the primary selection in the ParentDataGrid is changed. Therefore I want to avoid selecting DataGridRow in ParentDataGrid.
How to avoid selecting DataGridRow in ParentDataGrid by Clicking in DataGridDetailsPresenter?
This is my DataTemplate
<DataTemplate DataType="{x:Type MyViewModel}">
<DataTemplate.Resources>...
<Style TargetType="{x:Type DataGridRow}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridRow}">
<Border ...>
<SelectiveScrollingGrid>
<SelectiveScrollingGrid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</SelectiveScrollingGrid.ColumnDefinitions>
<SelectiveScrollingGrid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</SelectiveScrollingGrid.RowDefinitions>
<DataGridRowHeader Grid.Row="0" Grid.RowSpan="2" Grid.Column="0" .../>
<DataGridCellsPresenter Grid.Row="0" Grid.Column="1" .../>
<DataGridDetailsPresenter Grid.Row="1" Grid.Column="1" .../>
</SelectiveScrollingGrid>
</Border ...>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</DataTemplate.Resources>
<Grid ...>
<DataGrid x:Name="ParentDataGrid" ...>
<DataGrid.Columns>...</DataGrid.Columns>
<DataGrid.RowDetailsTemplate>
<DataTemplate>
<Grid ...>
<DataGrid x:Name="ChildDataGrid"...>...</DataGrid>
</Grid>
</DataTemplate>
</DataGrid.RowDetailsTemplate>
</DataGrid>
</Grid>
</DataTemplate>
Handle SelectedCellsChanged event in your parent DataGrid.
private void DataGrid_SelectedCellsChanged(object sender, SelectedCellsChangedEventArgs e)
{
DataGridRow row = (DataGridRow)DgrdParent.ItemContainerGenerator.ContainerFromItem(DgrdParent.SelectedItem);
if (row != null)
row.IsSelected = false;
}
And if you want to get the selected child DataGrid, you can use its SelectionChanged event.
<DataGrid x:Name="DgrdParent" ItemsSource="{Binding .}" CurrentCellChanged="DgrdParent_CurrentCellChanged_1" RowDetailsVisibilityMode="Visible" SelectionChanged="DgrdParent_SelectionChanged_1" SelectedCellsChanged="DataGrid_SelectedCellsChanged_1" >
<DataGrid.Resources>
<Style TargetType="DataGridDetailsPresenter">
</Style>
</DataGrid.Resources>
<DataGrid.RowDetailsTemplate>
<DataTemplate>
<DataGrid x:Name="DgrdChild" ItemsSource="{Binding Employees}" SelectionChanged="DataGridInner_SelectionChanged_1" />
</DataTemplate>
</DataGrid.RowDetailsTemplate>
</DataGrid>
Handler :
private void DataGridInner_SelectionChanged_1(object sender, SelectionChangedEventArgs e)
{
System.Diagnostics.Debug.WriteLine("DataGridInner_SelectionChanged_1 > Original source = " + ((DataGrid)sender).Name);
}

WPF ListBox Item collapse datatrigger not working

I have a listbox and all I want to do is collapse the listboxitem based on a boolean property of my SelectedItem.
The IsVisible property on my client Model implements the NotifyPropertyChanged event.
Overview - I have a list of clients which users can do CRUDs on. When they delete, I set a boolean property on the Model which my VM exposes to the View. This should then only hide the 'deleted' row from the list. During a flush to db I CRUD based on the mode of the model.
<ListBox Name="listClients"
Grid.Column="1" Grid.Row="1"
Margin="0" BorderThickness="0"
Height="auto"
Style="{StaticResource BumListBox}"
SelectionMode="Extended"
ItemsSource="{Binding Path=ClientList}"
SelectedItem="{Binding SelectedClient, Mode=TwoWay}"
Tag="{Binding DataContext, RelativeSource={RelativeSource AncestorType={x:Type ListBox}}}" >
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsVisible}" Value="False">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="50"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding ClientNo}" Foreground="White" FontSize="{StaticResource HeaderFontSize}" VerticalAlignment="Center" />
<TextBlock Grid.Column="1" Text="{Binding ClientDesc}" Foreground="White" FontSize="{StaticResource SubHeaderFontSize}" FontWeight="Light" VerticalAlignment="Center" />
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Code behind to jippo MVVM process:
private void Button_Click_1(object sender, RoutedEventArgs e)
{
if (_cvm.SelectedClient != null)
{
_cvm.SelectedClient.IsVisible = !_cvm.SelectedClient.IsVisible;
_cvm.CurrentSelectedIsVisible = _cvm.SelectedClient.IsVisible; //<- another option to bind to
}
}
I've tried the these suggestions here and here or something similar but I just can't get to hide the items.
Any help in the right direction would be great, cheers.
Edit
I've tried Blam's suggestion below like this but still unable to hide the items:
<ListBox.Resources>
<Style TargetType="ListBoxItem">
<Setter Property="Visibility" Value="{Binding Path=CurrentIsVisible, Converter={StaticResource b2v}}" />
</Style>
You will need to set up a converter if you are returning true/false but there is a system converter for that
Move it up to Resources
I have know I have used it this way
<ListBox x:Name="lb" ItemsSource="{Binding}" DisplayMemberPath="Text">
<ListBox.Resources>
<Style TargetType="ListBoxItem">
<Setter Property="Visibility" Value="{Binding Path=Vis}" />
</Style>
</ListBox.Resources>
</ListBox>
This was rather frustrating and the solution so simple. My client model with IsVisible is in a dll and the NotifyPropertyChanged() changes were never built to update the reference in my project..so the binding never happened. These late nights are taking their toll.

Switch ContentPresenter of ListBoxItem Based on Selection

I am trying to switch out the ContentPresenter of a ListBoxItem when it is selected, while using multiple DataTemplates to represent different types of data.
Here is the UserControl that defines the ListBox inside:
<UserControl x:Class="Homage.View.FilePanelView"
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:vw="clr-namespace:Homage.View"
xmlns:vm="clr-namespace:Homage.ViewModel"
xmlns:ctrl="clr-namespace:Homage.Controls"
mc:Ignorable="d">
<UserControl.Resources>
<DataTemplate DataType="{x:Type vm:SlugViewModel}">
<vw:SlugView />
</DataTemplate>
<DataTemplate DataType="{x:Type vm:HeaderSlugViewModel}">
<vw:HeaderSlugView />
</DataTemplate>
<DataTemplate DataType="{x:Type vm:ContentSlugViewModel}">
<vw:ContentSlugView />
</DataTemplate>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Border Name="SlugContainer" Background="Transparent" BorderBrush="Black" BorderThickness="1" CornerRadius="2" Margin="0,5,0,0" Padding="5">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Content="{Binding DisplayName}" />
<ContentPresenter Grid.Row="1" />
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="SlugContainer" Property="BorderThickness" Value="5" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<Grid>
<ListBox ItemsSource="{Binding Slugs}" Padding="5" />
</Grid>
</UserControl>
Based on the type of data to be shown (e.g., a "Header Slug") a certain DataTemplate is applied to the ListBoxItem. This is working great, but I am wanting to adjust the DataTemplate of the selected ListBoxItem to a different DataTemplate -- again, based on the data type being shown.
The goal is that, because each data type is different, each would have a unique look when not selected and would receive a unique set of options when selected.
If I can get the above to work, that would be great! But, I also want to complicate things...
While each data type has unique controls they also have common controls. So I would ideally like to define all the common controls once so that they appear in the same place in the ListBox.
<DataTemplate x:Key="CommonSelectedTemplate">
<!-- common controls -->
...
<DataTemplate x:Key="UniqueSelectedTemplate">
<!-- all the unique controls -->
<ContentPresenter />
</DataTemplate>
<!-- more common controls -->
...
</DataTemplate>
If I have to define all the common stuff multiple times (for now) I'll live. =)
Thanks for any help!
Let's suppose that we have only two data types: Item1ViewModel and Item2ViewModel. Therefore we need 4 data templates: 2 for the common state, 2 for the selected state.
<DataTemplate x:Key="Template1" DataType="local:Item1ViewModel">
<TextBlock Text="{Binding Property1}" Foreground="Red" />
</DataTemplate>
<DataTemplate x:Key="Template2" DataType="local:Item2ViewModel">
<TextBlock Text="{Binding Property2}" Foreground="Blue" />
</DataTemplate>
<DataTemplate x:Key="Template1Selected" DataType="local:Item1ViewModel">
<TextBlock Text="{Binding Property1}" Background="Yellow" Foreground="Red" />
</DataTemplate>
<DataTemplate x:Key="Template2Selected" DataType="local:Item2ViewModel">
<TextBlock Text="{Binding Property2}" Background="Yellow" Foreground="Blue" />
</DataTemplate>
For switching the content between two templates based on different types I use the DataTemplateSelector class:
public class SampleTemplateSelector:DataTemplateSelector
{
public DataTemplate Type1Template { get; set; }
public DataTemplate Type2Template { get; set; }
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
if (item is Item1ViewModel)
return Type1Template;
else if (item is Item2ViewModel)
return Type2Template;
return null;
}
}
We need two instances of this selector: one for the common state and one for the selected state.
<local:SampleTemplateSelector x:Key="templateSelector"
Type1Template="{StaticResource Template1}"
Type2Template="{StaticResource Template2}"/>
<local:SampleTemplateSelector x:Key="selectedTemplateSelector"
Type1Template="{StaticResource Template1Selected}"
Type2Template="{StaticResource Template2Selected}"/>
And after that you should add this code which switches two selectors:
<DataTemplate x:Key="ListItemTemplate">
<ContentControl x:Name="content" Content="{Binding}" ContentTemplateSelector="{StaticResource templateSelector}" />
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type ListBoxItem}},Path=IsSelected}" Value="True">
<Setter TargetName="content" Property="ContentTemplateSelector" Value="{StaticResource selectedTemplateSelector}"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
That's all, apply this ItemTemplate to your ListBox without changing the ControlTemplate:
<ListBox ItemsSource="{Binding Items}" ItemTemplate="{StaticResource ListItemTemplate}" />

Show "pop up window" when is mouser over listBox item

I bind observable collection on listBox. I have data tempate on listbox item. It consit one image control and som textBlock.
If is mouse over on some listBox item I would like achieve this behavior:
Show PopUp/ToolTip (some "rectangle" with controls) and bind values from listBox current item.
And on textBox in item data template I have style, I would like change color of text in textBlock, for example from black to green.
Style is here:
<Style x:Key="FriedNickStyle" TargetType="TextBlock">
<Setter Property="Margin" Value="2,2,2,2"/>
<Setter Property="FontSize" Value="13"/>
<Setter Property="FontWeight" Value="Medium"/>
<Setter Property="Foreground" Value="Black"/>
</Style>
Sory for my english, I have problem how describe this behavior correct. I try many thing but any of them doesn’t work good.
Here is it my style:
<DataTemplate x:Key="FriendListBoxItemTemplate">
<Grid Name="RootLayout">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.3*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="60"></RowDefinition>
</Grid.RowDefinitions>
<Image Margin="4,4,4,2" Grid.Column="0">
<Image.Source >
<MultiBinding Converter="{StaticResource avatarConverter}">
<Binding Path="ProfilePhoto"></Binding>
<Binding Path="StatusInfo.IsLogged"></Binding>
</MultiBinding>
</Image.Source>
</Image>
<Grid Grid.Column="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<TextBlock
Text="{Binding Path=Nick}"
Style="{StaticResource FriedNickStyle}"
Grid.Column="0" Grid.Row="0">
</TextBlock>
</Grid>
</Grid>
<DataTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<!--SHOW SOME POP UP WINDOW and bind properties from ITEM (VALUE)-->
<!--Change color of textBlock-->
</Trigger>
</DataTemplate.Triggers>
</DataTemplate>
Thank everybody who help me.
Well, I found this turorial, this article, by the MSDN and another stack overflow's question.
Basically, here's how:
<Popup Margin="10,10,0,13"
Name="Popup1"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Width="194"
Height="200"
IsOpen="True"> // change this to open it
<TextBlock Name="McTextBlock" Background="LightBlue" >
This is popup text
</TextBlock>

Resources