I have 2 comboboxs that has it's itemssource bound to 2 lists which are in a listview. This all works fine however when I add a new new item to the list the combobox values are blank and I want them to show me "All Zones" for one and "All Facies" in the other. How do I get this to work? I have tried many examples but all want me to use the "IsSynchronizedWithCurrentItem" to be true or the SelectedIndex to 0 however this also sets the current combobox values to the SelectedIndex which is not what I want I only want it if the combobox is blank. Can anyone please help me?
Combobox's inside the ListView
<GridViewColumn Width="100">
<GridViewColumn.CellTemplate>
<DataTemplate>
<ComboBox Style="{DynamicResource ComboBoxStyle1}" x:Name="zoneComboBox" Margin="0,0,5,0" Height="20" Width="80" ItemsSource="{Binding DataContext.Zones, RelativeSource={RelativeSource AncestorType={x:Type ListBox}, Mode=FindAncestor}}" SelectedValue="{Binding Zone}" SelectedIndex="0"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
<GridViewColumnHeader>
<TextBlock Text="Zones" FontFamily="{DynamicResource FontFamily}" FontSize="11" FontWeight="Bold"/>
</GridViewColumnHeader>
</GridViewColumn>
<GridViewColumn Width="100">
<GridViewColumn.CellTemplate>
<DataTemplate>
<ComboBox Style="{DynamicResource ComboBoxStyle1}" x:Name="faciesComboBox" Margin="0,0,5,0" Height="20" Width="80" ItemsSource="{Binding DataContext.Facies, RelativeSource={RelativeSource AncestorType={x:Type ListBox}, Mode=FindAncestor}}" SelectedValue="{Binding Facie}" SelectedIndex="0"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
<GridViewColumnHeader>
<TextBlock Text="Facies" FontFamily="{DynamicResource FontFamily}" FontSize="11" FontWeight="Bold"/>
</GridViewColumnHeader>
</GridViewColumn>
Add new rule method
private void AddRuleBtn_Click(object sender, RoutedEventArgs e)
{
rules.Add(new GeologicalAnalysisRule());
}
Observable Collection (Edit)
private ObservableCollection<GeologicalAnalysisRule> rules;
public RuleSetterControl()
{
InitializeComponent();
Rules = new ObservableCollection<GeologicalAnalysisRule>();
Rules.Add(new GeologicalAnalysisRule());
}
public ObservableCollection<GeologicalAnalysisRule> Rules
{
get { return rules; }
set
{
if (Equals(value, rules)) return;
rules = value;
OnPropertyChanged();
}
}
Instead of using private variable rules use Property Rules in the button click event.
private void AddRuleBtn_Click(object sender, RoutedEventArgs e)
{
Rules.Add(new GeologicalAnalysisRule());
}
Related
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.
I have a listview that pulls a bunch of computer numbers and information from a database and displays it. I have a little menu that will filter this listview. Currently, clicking the columns sorts the listview by ascending/descending, but I want this function to be triggered by radio buttons.
I'm basically trying to trigger the GridViewColumnHeader_Click method from the radiobutton method. Here is the GridViewColumnHeader_Click method:
private GridViewColumnHeader listViewSortCol = null;
private SortAdorner listViewSortAdorner = null;
private void GridViewColumnHeader_Click(object sender, RoutedEventArgs e)
{
GridViewColumnHeader column = (sender as GridViewColumnHeader);
string sortBy = column.Tag.ToString();
if (listViewSortCol != null)
{
AdornerLayer.GetAdornerLayer(listViewSortCol).Remove(listViewSortAdorner);
lstView.Items.SortDescriptions.Clear();
}
ListSortDirection newDir = ListSortDirection.Ascending;
if (listViewSortCol == column && listViewSortAdorner.Direction == newDir)
newDir = ListSortDirection.Descending;
listViewSortCol = column;
listViewSortAdorner = new SortAdorner(listViewSortCol, newDir);
AdornerLayer.GetAdornerLayer(listViewSortCol).Add(listViewSortAdorner);
lstView.Items.SortDescriptions.Add(new SortDescription(sortBy, newDir));
}
private void RbLocation_Checked(object sender, RoutedEventArgs e)
{
GridViewColumnHeader_Click(sender, RoutedEventArgs e);
}
<RadioButton x:Name="rbP2L" Content="P2L" MinWidth="40" Checked="RbP2L_Checked"/>
<RadioButton x:Name="rbAssy" Content="Assembly" Checked="RbAssy_Checked"/>
<RadioButton x:Name="rbLocation" Content="Location" MinWidth="40" Checked="{Binding GridViewColumnHeader_Click}"/>
I tried to do the same thing with a binding, not not sure if that's the right way. I was getting a error when trying to do a binding:
System.Windows.Markup.XamlParseException: ''Provide value on 'System.Windows.Data.Binding' threw an exception.'
I think this doesn't work because I'm not binding it to anything, because it's an event.
The listview is defined as such:
<ListView Name="lstView" SelectionChanged="lstView_SelectionChanged_1" MouseDoubleClick="LstView_MouseDoubleClick" Grid.Column="0" Background="LightGray" Margin="10,10,0,10" Grid.RowSpan="3">
<ListView.View>
<GridView>
<GridView.Columns>
<GridViewColumn Width="Auto">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding PCID}"></TextBlock>
</DataTemplate>
</GridViewColumn.CellTemplate>
<GridViewColumn.Header>
<GridViewColumnHeader>
<TextBlock Text="PCID" HorizontalAlignment="Stretch"></TextBlock>
</GridViewColumnHeader>
</GridViewColumn.Header>
</GridViewColumn>
<GridViewColumn Width="Auto">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding ProductionArea}"></TextBlock>
</DataTemplate>
</GridViewColumn.CellTemplate>
<GridViewColumn.Header>
<GridViewColumnHeader Tag="ProductionArea" Click="GridViewColumnHeader_Click">
<TextBlock Text="ProductionArea"></TextBlock>
</GridViewColumnHeader>
</GridViewColumn.Header>
</GridViewColumn>
<GridViewColumn Width="Auto">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Type}"></TextBlock>
</DataTemplate>
</GridViewColumn.CellTemplate>
<GridViewColumn.Header>
<GridViewColumnHeader Tag="Type" Click="GridViewColumnHeader_Click">
<TextBlock Text="Type"></TextBlock>
</GridViewColumnHeader>
</GridViewColumn.Header>
</GridViewColumn>
<GridViewColumn Width="auto">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Location}"></TextBlock>
</DataTemplate>
</GridViewColumn.CellTemplate>
<GridViewColumn.Header>
<GridViewColumnHeader Tag="Location" Click="GridViewColumnHeader_Click">
<TextBlock Text="Location"></TextBlock>
</GridViewColumnHeader>
</GridViewColumn.Header>
</GridViewColumn>
</GridView.Columns>
</GridView>
</ListView.View>
</ListView>
I figured I could use the tags to point to the header since everything has the same name, but I haven't been able to figure out the right wording. For example, how do I pass the Location header into the GridViewColumnHeader_Click method from outside of the click event? Thanks in advance, very stuck on this one.
To be honest, I don't understand what your problem is. In fact, you already have everything implemented.
Just in case, I'll show you an example.
using System;
using System.Collections.ObjectModel;
using System.Linq;
namespace Core2022.SO.AlexD.ManageGridViewColumn
{
public class SomeItem
{
public string Word { get; }
public int Value { get; }
public SomeItem(string word, int value)
{
Word = word;
Value = value;
}
private static ObservableCollection<SomeItem>? _itemsExample;
public static ObservableCollection<SomeItem> ItemsExample
{
get
{
if (_itemsExample is null)
{
Random random = new Random();
_itemsExample = new ObservableCollection<SomeItem>
(
"How to pass a GridViewColumnHeader object to a method?"
.Split()
.Select(word => new SomeItem(word, random.Next()))
);
}
return _itemsExample;
}
}
}
}
<Window x:Class="Core2022.SO.AlexD.ManageGridViewColumn.ManagerWindow"
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:Core2022.SO.AlexD.ManageGridViewColumn"
xmlns:specialized="clr-namespace:System.Collections.Specialized;assembly=netstandard"
xmlns:sys="clr-namespace:System;assembly=netstandard"
xmlns:componentmodel="clr-namespace:System.ComponentModel;assembly=System.ComponentModel.TypeConverter"
mc:Ignorable="d"
Title="ManagerWindow" Height="450" Width="800">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<ListView x:Name="itemsView" Grid.Row="1"
ItemsSource="{x:Static local:SomeItem.ItemsExample}">
<ListView.View>
<GridView>
<GridViewColumn Header="Word">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Word}"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Value">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Value}"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
<UniformGrid Columns="2" Rows="2">
<TextBlock Text="SortDirection"/>
<TextBlock Text="Column"/>
<ComboBox x:Name="directionsView"
SelectedIndex="0"
SelectionChanged="OnDirectionChanged">
<ComboBox.ItemsSource>
<CompositeCollection>
<componentmodel:ListSortDirection>Ascending</componentmodel:ListSortDirection>
<componentmodel:ListSortDirection>Descending</componentmodel:ListSortDirection>
</CompositeCollection>
</ComboBox.ItemsSource>
</ComboBox>
<ComboBox x:Name="propertiesView"
SelectedIndex="0"
SelectionChanged="OnPropertyChanged">
<ComboBox.ItemsSource>
<specialized:StringCollection>
<sys:String>Un Sort</sys:String>
<sys:String>Word</sys:String>
<sys:String>Value</sys:String>
</specialized:StringCollection>
</ComboBox.ItemsSource>
</ComboBox>
</UniformGrid>
</Grid>
</Window>
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
namespace Core2022.SO.AlexD.ManageGridViewColumn
{
public partial class ManagerWindow : Window
{
public ManagerWindow()
{
InitializeComponent();
}
private string oldProperty = string.Empty;
private ListSortDirection oldDirection;
private void OnPropertyChanged(object sender, SelectionChangedEventArgs e)
{
string property = (string)propertiesView.SelectedItem;
itemsView.Items.SortDescriptions.Clear();
if (property is not nameof(SomeItem.Word) and not nameof(SomeItem.Value))
{
oldProperty = string.Empty;
directionsView.Visibility = Visibility.Hidden;
}
else if (property != oldProperty)
{
oldProperty = property;
directionsView.Visibility = Visibility.Visible;
oldDirection = ListSortDirection.Ascending;
directionsView.SelectedIndex = 0;
itemsView.Items.SortDescriptions.Add(new SortDescription(property, oldDirection));
}
}
private void OnDirectionChanged(object sender, SelectionChangedEventArgs e)
{
ListSortDirection direction = (ListSortDirection)directionsView.SelectedItem;
if (direction != oldDirection)
{
oldDirection = direction;
itemsView.Items.SortDescriptions.Clear();
itemsView.Items.SortDescriptions.Add(new SortDescription(oldProperty, direction));
}
}
}
}
I want to get all the items in a listview that the checkbox has checked.
<ListView x:Name="lvwStudent" IsSynchronizedWithCurrentItem="True" SelectionMode="Multiple" HorizontalAlignment="Stretch" HorizontalContentAlignment="Center" VerticalContentAlignment="Center">
<ListView.View>
<GridView>
<GridViewColumn Width="50">
<GridViewColumn.CellTemplate>
<DataTemplate>
<CheckBox x:Name="cboxSelected" Content ="{Binding ID}" Width="20" Height="20" BorderBrush="#FF0C6161" HorizontalAlignment="Center" HorizontalContentAlignment="Center" Tag="{Binding ID}" IsChecked="{Binding IsChecked}" Checked="cboxSelected_Checked_1" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="NO." Width="53">
<GridViewColumn.CellTemplate>
<DataTemplate >
<Label Content ="{Binding ID}" FontSize="14" HorizontalContentAlignment="Center"></Label>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="STUDENT NAME" Width="auto">
<GridViewColumn.CellTemplate>
<DataTemplate>
<Label Content ="{Binding STUDENT_NAME}" FontSize="14" HorizontalContentAlignment="Center"></Label>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
when I click the select button I want to get all selected ID and store in an array.
private void btnSelect_Click(object sender, RoutedEventArgs e)
{
int[] selectedId;
if(lvwMachine.SelectedItems.Count > 0)
{
foreach(..... )
{
//add all selected id in array selectedId
}
}
List<Student>StudentList = new Students().getStudent();
List<ListViewItem> ITEM = new List<ListViewItem>();
foreach (var s in StudentList)
{
ListViewItem OneItem = new ListViewItem();
OneItem.Content = new Student()
{ID = s.ID, STUDENT_NAME = s.name};
ITEM.Add(OneItem);
lvwMachine.ItemsSource = ITEM;
}
You can try this:
lvwMachine.ItemsSource.Where(element => element.IsChecked).ToArray();
I need help with buttons in list view. I am creating custom form for SCSM. List view is working without problems, but I need add there Add button, Open button and Delete button. Add button working without problem, but other buttons do nothing. Can anybody help me with it?
Thanks
XAML code is here:
<ListView Name="ListViewMonitor" VerticalAlignment="Top" HorizontalAlignment="Stretch" Margin="10,0,00,0" MinHeight="100" Grid.Column="0" Grid.Row="1" ItemsSource="{Binding Path=CustomRelatedMonitor, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}">
<ListView.View>
<GridView>
<GridViewColumn Header="{Binding Path=Strings[ID].Value, FallbackValue=ID, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type views:FormView}}}" DisplayMemberBinding="{Binding Path=ID}" Width="Auto"/>
<GridViewColumn Header="{Binding Path=Strings[CustomAssetStatus].Value, FallbackValue=CustomAssetStatus, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type views:FormView}}}" Width="Auto">
<GridViewColumn.CellTemplate>
<DataTemplate>
<smcontrols:ListPicker Name="listPickerAssetStatus" HorizontalAlignment="Stretch" Width="Auto" ParentCategoryId="{Binding Source=12435943-EBA1-3E78-BB6C-A731E44EDCFD, Mode=OneWay}" SelectedItem="{Binding Path=CustomAssetStatus, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
<StackPanel Margin="10,0,10,0" Grid.Row="1" Grid.Column="1" VerticalAlignment="Top" HorizontalAlignment="Right">
<Button VerticalAlignment="Top" HorizontalAlignment="Right" Name="buttonAddMonitor" Height="20" Width="65" Content="{Binding Path=Strings[buttonAdd].value, FallbackValue=Add, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type views:FormView}}}" Click="buttonAddMonitor_Click" />
<Button VerticalAlignment="Top" HorizontalAlignment="Right" Margin="0,10,0,0" Name="buttonRemoveMonitor" Height="20" Width="65" IsEnabled="{Binding ElementName=ListViewMonitor, Path=SelectedItems.Count}" Content="{Binding Path=Strings[buttonRemove].value, FallbackValue=Remove, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type views:FormView}}}" Click="buttonRemoveMonitor_Click" />
<Button VerticalAlignment="Top" HorizontalAlignment="Right" Margin="0,10,0,0" Name="buttonOpenMonitor" Height="20" Width="65" IsEnabled="{Binding ElementName=ListViewMonitor, Path=SelectedItems.Count}" Content="{Binding Path=Strings[buttonOpen].value, FallbackValue=Open, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type views:FormView}}}" Click="buttonOpenMonitor_Click" />
</StackPanel>
Code for buttons:
public ListView ListViewAllMonitors { get; set; }
private ListView GetListView (string Name)
{
switch (Name)
{
case "buttonAddMonitor":
case "buttonRemoveMonitor":
case "buttonOpenMonitor":
{
return this.ListViewAllMonitors;
}
default:
{
throw new Exception(String.Format("ListView for control: {0}- not found", Name));
}
}
}
private void buttonAddMonitor_Click(object sender, RoutedEventArgs e)
{
ButtonAdd_Click(new Guid("DD3BDB96-BC9E-D46E-5847-BAB387039B36"), ListViewMonitor);
}
private void ButtonAdd_Click(Guid mpClassGuid, ItemsControl listView)
{
FormUtilities.Instance.LaunchAddInstancePickerDialog(listView.ItemsSource as Collection<IDataItem>, mpClassGuid);
}
private void buttonRemoveMonitor_Click(object sender, RoutedEventArgs e)
{
var button = (Button)sender;
var CustomListView = GetListView(button.Name);
if (CustomListView == null) return;
var list = (IList<IDataItem>)CustomListView.ItemsSource;
if (list == null) return;
foreach (IDataItem item in new ArrayList(CustomListView.SelectedItems))
{
list.Remove(item);
}
}
private void buttonOpenMonitor_Click(object sender, RoutedEventArgs e)
{
var button = (Button)sender;
var ListView = GetListView(button.Name);
if (ListView == null) return;
OpenInstance(ListView);
}
public void OpenInstance(ListView ListView)
{
if (ListView == null) return;
foreach (IDataItem dataItem in ListView.SelectedItems)
{
FormUtilities.Instance.PopoutForm(dataItem);
}
}
I'm trying to use the event trigger from Blend to fire a button click event of a listview item, it should work so that the item does not have to be selected for the relevant row to be referenced.
My code is...
Public void MyCommand(object obj)
{
// the tag of this has the search type
ListViewItem item = obj as ListViewItem;
// do my dreary domain work...
}
my xaml is...
<ListView ItemsSource="{Binding Path=SystemSetupItems}"
SelectedItem="{Binding Selected, Mode=TwoWay}"
MinHeight="120" >
<ListView.View>
<GridView>
<GridViewColumn Header="Name" DisplayMemberBinding="{Binding Name}" />
<GridViewColumn Header="Description" DisplayMemberBinding="{Binding Description}" />
<GridViewColumn>
<GridViewColumn.CellTemplate>
<DataTemplate>
<Button >
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseClick">
<i:InvokeCommandAction CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=ListViewItem, AncestorLevel=1}}" Command="{Binding MyCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
but this doesn't work at all, alternatively I can do this in my xaml button definition
<GridViewColumn.CellTemplate>
<DataTemplate>
<Button Command="{Binding OpenWorkSpaceCommand}" CommandParameter="{Binding Path=Name}" Content="Edit..." DataContext="{Binding DataContext, RelativeSource={RelativeSource FindAncestor, AncestorType=ListView}}" >
</Button>
</DataTemplate>
</GridViewColumn.CellTemplate>
but this required the listview item to be previously selected, which is not the behaviour I want.
For my DataGrid I have a button on each item using the cell template. Each item is an object of type Meal. In my Meal.cs file I have an event definition like so:
public Meal()
{
RemoveMealCommand = new RelayCommand(() => RemoveMealCommandExecute());
}
public RelayCommand RemoveMealCommand
{
get;
set;
}
public delegate void RemoveMealEventHandler(object sender, EventArgs e);
public event RemoveMealEventHandler RemoveMealEvent;
private void RemoveMealCommandExecute()
{
RemoveMealEvent(this, null);
}
In my viewmodel for every meal in my list I can just add a handler to that event. And for my xaml button I just set the command to the Meal's RelayCommand.
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button Command="{Binding Path=RemoveMealCommand}">
<Image Width="13" Height="13" Source="/Images/delete-icon.png"/>
</Button>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
Now when you click the button the Meal is responsible for firing the event and the viewmodel is responsible for handling it.