XAML Get Item text value from ListViewItem - c#

I have a ListView Control witch item is composite by two TextBlocks like that:
<ListView x:Name="resultsList" ItemsSource="{Binding}" HorizontalAlignment="Left" Height="470" Margin="10,0,0,0" VerticalAlignment="Top" Width="342" FontSize="21.333" BorderThickness="0" ItemClick="RedirectPage" IsItemClickEnabled="True" SelectionMode="None">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,-4,0,-4">
<StackPanel.Resources>
<Style TargetType="TextBlock">
<Setter Property="Margin" Value="0,0,0,0" />
</Style>
</StackPanel.Resources>
<TextBlock FontSize="35" Text="{Binding target_name}" />
<TextBlock FontSize="15" Text="{Binding type_name}" Opacity="30" Margin="0, 0, 0 ,30"/>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
In the code behind I am trying to get as string the text value from first TextBlock element.
string targetName;
targetName = resultsList.SelectedItem.ToString();
I want that Variable "targetName" то assign the text value ( Text="{Binding target_name}" ) from first TextBlock in the ListView Item.
I will be very thankful if someone is able to help me.

resultsList.SelectedItem should be the object from the collection that is bound to the ListView. So, you can just cast it to the appropriate type and then access the target_name member

Itemssource should be collection. You need to typecast the collection to get the value.
class listData
{
public string target_name { get; set; }
public string type_name{ get; set; }
}
You can get values like this
listData ld= (listData)resultsList.SelectedItem;
string targetName =ld.target_name;

Related

Binding parameter to a nested ListView using SelectedItem

I'm pretty new to coding in c# and I'm trying on a wpf app to transfer data between different folders.
To visualize the folders and subfolders I've got a tabcontrol with different mainfolders, and under each tab a ListView with information on the subfolders.
All data is gathered in a BindingList 'Klinieken', which is filled with objects 'Kliniek' (mainfolders) which contains objects 'Patient' (subfolders) which is filled with information about said folder. Here is the .xaml file for the mainwindow:
<Grid x:Name="LayoutRoot" Background="#555555">
<Grid.RowDefinitions>
<RowDefinition Height="420" />
<RowDefinition Height="116" />
</Grid.RowDefinitions>
<Grid x:Name="KliniekTabs" Background="#555555" Grid.Row="0" Margin="10 10 10 10">
<TabControl ItemsSource="{Binding Klinieken}"
SelectedItem="{Binding BronKliniek}"
TabStripPlacement="Top">
<TabControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding KliniekNaam}" />
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<DataTemplate>
<ListView ItemsSource="{Binding Path=Patienten}"
SelectedItem="{Binding Path=SelectedPatient}">
<ListView.Resources>
<Style TargetType="{x:Type GridViewColumnHeader}">
<Setter Property="HorizontalContentAlignment" Value="Left"/>
</Style>
</ListView.Resources>
<ListView.View>
<GridView>
<GridViewColumn Header="Patientnaam"
Width="250"
DisplayMemberBinding="{Binding PatientNaam}"/>
<GridViewColumn Header="Zisnr"
Width="250"
DisplayMemberBinding="{Binding PatientZis}"/>
<GridViewColumn Header="Aanmaakdatum"
Width="250"
DisplayMemberBinding="{Binding AanmaakDatum}"/>
</GridView>
</ListView.View>
</ListView>
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
</Grid>
<Grid x:Name="WindowControls" Background="#777777" Grid.Row="1" Margin="100 5 100 10">
<StackPanel Orientation="Vertical">
<Label Margin="-80 0 0 0" HorizontalAlignment="Center">Doel kliniek</Label>
<ComboBox ItemsSource="{Binding Path=Klinieken}"
x:Name="doelKliniekDD"
SelectedItem="{Binding DoelKliniek}"
Margin="-120 0 0 0"
HorizontalAlignment="Center">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=KliniekNaam}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<StackPanel Orientation="Horizontal" Margin="20 0 0 0" Height="50" VerticalAlignment="Bottom" HorizontalAlignment="Center">
<Button Height="25" Style="{StaticResource Button_Orange}" Command="{Binding TransferButtonCommand}" CommandParameter="{Binding ElementName=window, Mode=OneWay}" Margin="0 0 10 0">Transfer</Button>
<Button Height="25" Style="{StaticResource Button_Orange}" Command="{Binding CopyButtonCommand}" CommandParameter="{Binding ElementName=window, Mode=OneWay}" Margin="10 0 20 0">Kopieer</Button>
<Button Height="25" Style="{StaticResource Button_Grey}" Command="{Binding CloseCommand}" CommandParameter="{Binding ElementName=window, Mode=OneWay}" Margin="20 0 0 0">Cancel</Button>
</StackPanel>
</StackPanel>
</Grid>
</Grid>
And here is the MainViewModel that is referenced in the .xaml:
//attributen
string monacoDirectory;
List<string> aanwezigeClinics;
Installation installation;
//constructor
public MainViewModel()
{
monacoDirectory = ConfigurationManager.AppSettings["monacoDirectory"];
aanwezigeClinics = new List<string>(Directory.GetDirectories(monacoDirectory, "*", SearchOption.TopDirectoryOnly));
aanwezigeClinics.Remove(monacoDirectory + #"\defaults");
aanwezigeClinics.Remove(monacoDirectory + #"\physics");
installation = new Installation(aanwezigeClinics);
Klinieken = new BindingList<Kliniek>();
foreach (var kliniek in installation.Klinieken)
{
Klinieken.Add(kliniek);
}
}
private Kliniek _doelKliniek;
private Kliniek _bronKliniek;
private Patient _selectedPatient;
private BindingList<Kliniek> _klinieken = new BindingList<Kliniek>();
public BindingList<Kliniek> Klinieken
{
get { return _klinieken; }
set { _klinieken = value; }
}
public Kliniek DoelKliniek
{
get { return _doelKliniek; }
set
{
_doelKliniek = value;
OnPropertyChanged();
}
}
public Kliniek BronKliniek
{
get { return _bronKliniek; }
set
{
_bronKliniek = value;
OnPropertyChanged();
}
}
public Patient SelectedPatient
{
get { return _selectedPatient; }
set
{
_selectedPatient = value;
MessageBox.Show("hoi");
OnPropertyChanged();
}
}
The data shows up in the gui just fine, which i was quite happy with. And using SelectedItem on the TabControl and the ComboBox i use later worked out beautifully aswell, but I just cant seem to get the SelectedItem on the ListView to work. I have added a button to test the output of the fields and SelectedPatient always returns as null.
If i check the 'Live Visual Tree' in VS and go to the properties of the ListView i can see the Patient as SelectedItem, so that tells me its not a selection but a binding problem. Furthermore ive tried to google for nested bindings, but the suggestions there didnt change anything about my situation.
Is a nested binding like this possible, or should i take a whole different approach?
Had a similar problem quite a while ago. The suggestions below solved it for me at the time.
Use SelectedValue instead of SelectedItem. This is because SelectedItem doesn't change until the control has been validated. SelectedValue changes whenever the user selects an item. The code you could use is as follows:
SelectedValue="{Binding BronKliniek, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
For the button part, try to provide CommandParameter="{Binding}" instead of CommandParameter="{Binding ElementName=window, Mode=OneWay}". This way, you'll get the value of the current DataContext of the button, which you can then use to extract the data you want from this DataContext.

WPF Combox using Itemteplate with multiple sources

I am trying to make WPF Combobox using ItemTemplate. My idea is to create items in combobox like in this tutorial https://www.wpf-tutorial.com/list-controls/combobox-control/, but slightly different. I have 2 Lists, which I want to use as source. A List containing colors for Rectangles = colorList, and a list containing strings for TextBlocks = classesList
List<System.Windows.Media.SolidColorBrush> colorList = new List<System.Windows.Media.SolidColorBrush>
List<string> classesList = new List<string>
<ComboBox Name="cmbClasses" ItemsSource=" ??? " SelectionChanged="cmbClasses_SelectionChanged" Margin="10" >
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Rectangle Name="rectSelectedClassColor" Fill=" ??? " Width="16" Height="16" Margin="0,2,5,2" />
<TextTextBlock Name="cboxSelectedClass" Text=" ??? " MinWidth="50" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
Is it possible? How? Thank you.
You should make a new class with a string and Solid color brush as properties
public class NewClass
{
public string Name {get;set;}
public SolidColorBrush Brush {get;set;}
}
Then should make an ObservableCollection of this class and Bind it to your combobox.
ObservableCollection<NewClass> Source = new ObservableCollection<NewClass>();
XAML could look like this.
<ComboBox ItemSource = "{Binding Source}">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<Rectangle Fill = "{Binding Brush}"/>
<TextBlock Text = "{Binding Name}"/>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>

Binding collection of many types to RadTileView with specified Tile spans

I am trying to create view using Telerik for WPF. The View should present collection loaded in VM after button click. Every element from collection is inheriting from base class:
public class BindableProfileData : BindableBase
{
private ProfileItem _profileModel;
private BindableDPDataItem _dataModel;
public int Row
{
get { return _profileModel.DrawingSettings.Row; }
}
public int Column
{
get
{
return _profileModel.DrawingSettings.Column;
}
}
public int RowSpan
{
get { return _profileModel.DrawingSettings.RowSpan; }
}
public int ColumnSpan
{
get { return _profileModel.DrawingSettings.ColumnSpan; }
}
}
so for example in collection may appear object of
BarContainer : BindableProfileData {}
Now to present content i created that view:
<Grid>
<FrameworkElement.Resources>
<DataTemplate x:Key="ItemTemplate" >
<TextBlock Text="{Binding Name}" />
</DataTemplate>
<DataTemplate x:Key="ContentTemplate">
<StackPanel>
<TextBlock Text="{Binding Row, StringFormat='Row: {0}'}"/>
<TextBlock Text="{Binding Column, StringFormat='Column: {0}'}"/>
<TextBlock Text="{Binding RowSpan, StringFormat='RowSpan: {0}'}"/>
<TextBlock Text="{Binding ColumnSpan, StringFormat='ColumnSpan: {0}'}"/>
</StackPanel>
</DataTemplate>
</FrameworkElement.Resources>
<Grid>
<telerik:RadTileView x:Name="xTileView"
ItemTemplate="{StaticResource ItemTemplate}"
ContentTemplate="{StaticResource ContentTemplate}"
ItemsSource="{Binding SelectedCategory}"
IsAutoScrollingEnabled="True"
ColumnWidth="500"
RowHeight="300">
<telerik:RadTileView.ItemsPanel>
<ItemsPanelTemplate>
<controlls:MultipleRowsAndColumnsPanel RowsCount="4" ColumnsCount="3"/>
</ItemsPanelTemplate>
</telerik:RadTileView.ItemsPanel>
<telerik:RadTileView.ItemContainerStyle>
<Style TargetType="telerik:RadTileViewItem">
<Setter Property="controlls:TileViewAttachedProperties.Row" Value="{Binding Row}"/>
<Setter Property="controlls:TileViewAttachedProperties.Column" Value="{Binding Column}"/>
<Setter Property="controlls:TileViewAttachedProperties.RowSpan" Value="{Binding RowSpan}"/>
<Setter Property="controlls:TileViewAttachedProperties.ColumnSpan" Value="{Binding ColumnSpan}"/>
</Style>
</telerik:RadTileView.ItemContainerStyle>
</telerik:RadTileView>
</Grid>
</Grid>
Which uses helpers from telerik guides (MultipleRowsAndColumnsPanel, TileViewAttachedProperties)
I have two problems. First why view not appears after Collection change.
When I cut:`
<telerik:RadTileView.ItemsPanel>
<ItemsPanelTemplate>
<controlls:MultipleRowsAndColumnsPanel RowsCount="4" ColumnsCount="3"/>
</ItemsPanelTemplate>
</telerik:RadTileView.ItemsPanel>
`
from code and paste it again (Visual Studio edit and run) view appears just How I want it to be. So it looks like ItemsPanel not reacting on collection Change, but how to fix it?
And the second question how can I specify different templates for different classes in collection. I found similar post but I don't know how to do it with RadViewTableItem because it has two elements (ItemTemplate and ContentTemplate) usually specified in RadTileView.
Any advice whould be very helpfull for me. Thank you :)

MVVM-How to Binding ObservableCollection of Strings into ListBox WPF

Normally I bind ObservableCollection to my own classes. But in this case I need to bind ObservableCollection of Strings in ListBox using MVVM into WPF.
My xml is
<Window x:Class="ListBoxDynamic.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"
xmlns:vm="clr-namespace:ListBoxDynamic.ViewModel">
<Grid Margin="0,0,-8,0">
<ListBox Width="100" Height="90" ItemsSource="{Binding ListOfItems}">
<ListBox.ItemTemplate>
<DataTemplate>
<ToggleButton Command="{Binding SelectItemCommand}" CommandParameter="{Binding ElementName=Item}" >
<ToggleButton.Template>
<ControlTemplate TargetType="ToggleButton">
<TextBlock x:Name="Item" Text="{Binding What I must to write?}" />
</ControlTemplate>
</ToggleButton.Template>
</ToggleButton>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
My MainViewModel
private ObservableCollection<string> _listOfItems = new ObservableCollection<string>();
public ObservableCollection<string> ListOfItems
{
get { return _listOfItems; }
set { _listOfItems = value; RaisePropertyChanged("ListOfItems"); }
}
public ICommand SelectItemCommand { get; private set; }
int counter = 1;
public MainViewModel()
{
ListOfItems.Add("Add new Item");
SelectItemCommand = new RelayCommand<object>((x) => ExecuteSelectItemCommand(x));
}
But I don't know that I must to write in Binding TextBlock into ToggleButton.
Since data which back each ListBoxItem is string, hence DataContext of each ListBoxItem will be string.
Hence doing <TextBlock x:Name="Item" Text="{Binding }" /> will show you the string backing the listboxitem in the textblock
there are few issues I notices
the command is available in the view model instead of the data item, so use relative source to bind to command
"{Binding}" can be used to refer to current Item, so no need to use elementname syntax
then instead of placing a textbox inside toggle button you can make use of content presenter to make it more flexible
so this could go like this
<ListBox Width="100"
Height="90"
ItemsSource="{Binding ListOfItems}">
<ListBox.ItemTemplate>
<DataTemplate>
<ToggleButton Command="{Binding SelectItemCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ListBox}}"
CommandParameter="{Binding}"
Content="{Binding}">
<ToggleButton.Template>
<ControlTemplate TargetType="ToggleButton">
<ContentPresenter />
</ControlTemplate>
</ToggleButton.Template>
</ToggleButton>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>

Combo box add item from template

Im trying to add items to the combo box from the code behind to the item template but im getting null. This is what I have so far:
XAML:
<ListBox x:Name="lsbCiertoYFalsoInsideTemplate" Margin="40,0,0,0" ItemTemplate="{StaticResource CiertoYFalsoExcerciseDataTemplate}"/>
App.xaml:
<DataTemplate x:Key="CiertoYFalsoExcerciseDataTemplate">
<Grid>
<StackPanel x:Name="stckCiertoYFalsoInsideTemplate" Margin="0" Orientation="Vertical" Width="1100">
<StackPanel x:Name="stckPreguntasCiertoYFalso" Orientation="Horizontal">
<Grid Height="50" Width="65" DataContext="{Binding CustomValueList}" VerticalAlignment="Top">
<ComboBox x:Name="cbExercises" Style="{StaticResource SA_ComboBoxStyle}" ItemsSource="{Binding CustomOption}" BorderBrush="#CC8C8C8C" VerticalAlignment="Top">
</ComboBox>
</Grid>
<TextBlock HorizontalAlignment="Center" Margin="5,3,0,0" TextWrapping="Wrap" Text="{Binding QuestionNumber}" VerticalAlignment="Top" FontWeight="Bold" Foreground="Black" Width="26" FontFamily="{Binding FontFamily, Source={StaticResource TextBlockStyleManager}}" FontSize="{Binding FontSize, Source={StaticResource TextBlockStyleManager}}"/>
<TextBlock TextWrapping="Wrap" Text="{Binding Question}" Foreground="Black" VerticalAlignment="Top" FontSize="{Binding FontSize, Source={StaticResource TextBlockStyleManager}}" Margin="10,3,0,0" Width="968" FontFamily="{Binding FontFamily, Source={StaticResource TextBlockStyleManager}}"/>
</StackPanel>
</StackPanel>
</Grid>
</DataTemplate>
The error im getting is object out of range.
Code:
private void ComboBoxExercises()
{
ComboBox comboBox = new ComboBox();
ComboboxItem item = new ComboboxItem();
item.Text = "A";
comboBox = (ComboBox)lsbCiertoYFalsoInsideTemplate.FindName("cbExercises");
comboBox.SelectedIndex = 0;
comboBox.Items.Add(item);
}
public class ComboboxItem
{
public string Text { get; set; }
public override string ToString()
{
return Text;
}
}
There's a disconnect in what you're trying to do here. You've specified an ItemTemplate - which defines how each item in the list will look.
But then you're trying to get one single ComboBox back out via the FindName function. Which leads me to believe that you're really intending to set the Template, not the ItemTemplate.
That said, I think the error you're getting is because you're setting the SelectedIndex to 0 when the ComboBox has no items in it. You're telling it to select the first one, but there's nothing to select. You should add the item first, then select it.

Categories