WPF Combobox w/ Observable Collection in Composite Collection - c#

I'm trying to populate a combobox with an observable collection and a header row using a composite collection. The header is there but I can't get the OC objects to populate. I'm just starting to use OC's so might be something basic I'm missing.
Customer class:
public class Customer : ViewModelBaseMain
{
public string CustomerName { get; set; }
public int CustomerId { get; set; }
}
I populate the OC, which is a dependency property, from a datatable (I verified that the OC is being populated correctly):
ObservableCollection<Customer> dpCustomerListOC = new ObservableCollection<Customer>();
foreach (DataRow drow in dpHeaderCustTable.Rows)
{
Customer Customer = new Customer();
Customer.CustomerId = Convert.ToInt32(drow["customer_id"]);
Customer.CustomerName = drow["customer_name"].ToString();
dpCustomerListOC.Add(Customer);
}
In the usercontrol resources, I specify the VM as a static resource:
<local:ReservationViewModel x:Key="ReserveVM"/>
I've tried two different ways from posts I've read.
First way w/ collection in the resources using x:reference:
<ComboBox x:Name="cboCustHeader" Grid.IsSharedSizeScope="True" IsEditable="False"
ItemsSource="{DynamicResource items}">
<ComboBox.Resources>
<CompositeCollection x:Key="items">
<ComboBoxItem IsEnabled="False">
<Border Style="{StaticResource ComboHeaderBorder}">
<Grid Style="{StaticResource ComboHeaderStyle}">
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="A"/>
<ColumnDefinition Width="7"/>
<ColumnDefinition SharedSizeGroup="B"/>
</Grid.ColumnDefinitions>
<Grid.Children>
<TextBlock Grid.Column="0" Text="ID"/>
<TextBlock Grid.Column="2" Text="Name"/>
</Grid.Children>
</Grid>
</Border>
</ComboBoxItem>
<CollectionContainer Collection="{Binding Source={x:Reference cboCustHeader}, Path=DataContext.dpCustomerListOC}"/>
</CompositeCollection>
</ComboBox.Resources>
<ComboBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="A"/>
<ColumnDefinition Width="7"/>
<ColumnDefinition SharedSizeGroup="B"/>
</Grid.ColumnDefinitions>
<Grid.Children>
<TextBlock Text="{Binding Path=CustomerId, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
<TextBlock Text="{Binding Path=CustomerName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</Grid.Children>
</Grid>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
Second way specifying the source:
<ComboBox x:Name="cboCustHeader" Grid.IsSharedSizeScope="True">
<ComboBox.ItemsSource>
<CompositeCollection>
<ComboBoxItem IsEnabled="False">
<Border Style="{StaticResource ComboHeaderBorder}">
<Grid Style="{StaticResource ComboHeaderStyle}">
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="A"/>
<ColumnDefinition Width="7"/>
<ColumnDefinition SharedSizeGroup="B"/>
</Grid.ColumnDefinitions>
<Grid.Children>
<TextBlock Grid.Column="0" Text="ID"/>
<TextBlock Grid.Column="2" Text="Name"/>
</Grid.Children>
</Grid>
</Border>
</ComboBoxItem>
<CollectionContainer Collection="{Binding Path=dpCustomerListOC, Source={StaticResource ReserveVM}}"/>
</CompositeCollection>
</ComboBox.ItemsSource>
<ComboBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="A"/>
<ColumnDefinition Width="7"/>
<ColumnDefinition SharedSizeGroup="B"/>
</Grid.ColumnDefinitions>
<Grid.Children>
<TextBlock Grid.Column="0" Text="{Binding Path=CustomerId, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
<TextBlock Grid.Column="2" Text="{Binding Path=CustomerName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</Grid.Children>
</Grid>
</DataTemplate>
</ComboBox.ItemTemplate>

Add a public property exposing the collection on your view model:
public ObservableCollection<Customer> DpCustomerListOC
{
get { return dpCustomerListOC; }
}
And bind the combo's ItemsSource to it:
<ComboBox x:Name="cboCustHeader" Grid.IsSharedSizeScope="True">
<ComboBox.ItemsSource>
<CompositeCollection>
<ComboBoxItem IsEnabled="False">
<Border Style="{StaticResource ComboHeaderBorder}">
<Grid Style="{StaticResource ComboHeaderStyle}">
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="A"/>
<ColumnDefinition Width="7"/>
<ColumnDefinition SharedSizeGroup="B"/>
</Grid.ColumnDefinitions>
<Grid.Children>
<TextBlock Grid.Column="0" Text="ID"/>
<TextBlock Grid.Column="2" Text="Name"/>
</Grid.Children>
</Grid>
</Border>
</ComboBoxItem>
<CollectionContainer Collection="{Binding Path=DpCustomerListOC, Source={StaticResource ReserveVM}}"/>
</CompositeCollection>
</ComboBox.ItemsSource>
<ComboBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="A"/>
<ColumnDefinition Width="7"/>
<ColumnDefinition SharedSizeGroup="B"/>
</Grid.ColumnDefinitions>
<Grid.Children>
<TextBlock Grid.Column="0" Text="{Binding Path=CustomerId, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
<TextBlock Grid.Column="2" Text="{Binding Path=CustomerName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</Grid.Children>
</Grid>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
Make sure the collection is populated in the constructor.

It seems like you are missing to NotifyPropertyChange. When working with ComboBoxs I usually just do something like this:
<ComboBox ItemsSource="{Binding Customers, Mode=OneWay}"
SelectedItem="{Binding SelectedCustomer, Mode=TwoWay}"> </ComboBox>
Then in your class:
public type Customers
{
get{return _Customers}
set{_SelectedCustomer = value;
NotifyPropertyChanged("Customers");}
}
public type SelectedCustomer
{
get{return _SelectedCustomer;}
set{_SelectedCustomer = value;
NotifyPropertyChanged("SelectedCustomer")}
}
The syntax may be off a little bit but something like this should populate the ComboBox.

Related

MultiBinding of grid visiblity in WPF

I have a list view Item
and I want to collapse some of the items in the row of the list
I am using the grid for editing the data template.
I tried to work with multi-binding for the parameter
however I got that "DependencyProperty.UnsetValue"
would be happy for a code example.
if I am using 1 parameter all good.
can someone please explain to me how to use multi-binding
would be happy with a code example.
thanks.
Working code for 1 parmaeter I can use this code:
<ListView x:Name="LVGuiCoreBus" ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.HorizontalScrollBarVisibility="Auto" MouseDown="LVGui_MouseDown" Grid.Row="1" >
<ListView.ItemTemplate>
<DataTemplate>
<Grid Visibility="{Binding Source, Converter={StaticResource VisiblieGroupFilterBySourcecs}}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="130"></ColumnDefinition>
<ColumnDefinition Width="10"></ColumnDefinition>
<ColumnDefinition Width="50"></ColumnDefinition>
<ColumnDefinition Width="10"></ColumnDefinition>
<ColumnDefinition Width="50"></ColumnDefinition>
<ColumnDefinition Width="10"></ColumnDefinition>
<ColumnDefinition Width="100"></ColumnDefinition>
<ColumnDefinition Width="10"></ColumnDefinition>
<ColumnDefinition Width="70"></ColumnDefinition>
<ColumnDefinition Width="10"></ColumnDefinition>
<ColumnDefinition Width="150"></ColumnDefinition>
<ColumnDefinition Width="10"></ColumnDefinition>
<ColumnDefinition Width="150"></ColumnDefinition>
<ColumnDefinition Width="10"></ColumnDefinition>
<ColumnDefinition Width="1*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding DateNTimeStr}" Foreground="Green" Grid.Column="0" />
<TextBlock Text="{Binding Source}" Foreground="{Binding Source,Converter={StaticResource CoreBusPanelModuleColorConverter}}" Grid.Column="2" Background="{ Binding Source, Converter={StaticResource BackGroundFilterConverterBySource}}" />
<TextBlock Text="{Binding Destination}" Foreground="{Binding Destination,Converter={StaticResource CoreBusPanelModuleColorConverter}}" Grid.Column="4" Background="{ Binding Destination, Converter={StaticResource BackGroundFilterConvertorByDestantation}}" />
<TextBlock Text="{Binding Module}" Grid.Column="6" HorizontalAlignment="Center" Background="{ Binding Module, Converter={StaticResource BackGroundFilterByModule}}" />
<TextBlock Text="{Binding Controll}" Grid.Column="8" Background="{ Binding Controll, Converter={StaticResource BackGRoundFilterByControll}}" />
<TextBlock Text="{Binding Command}" Grid.Column="10" HorizontalAlignment="Center" Background="{ Binding Command, Converter={StaticResource BackGroundFilterByCommand}}" />
<TextBlock Text="{Binding HSCommand}" Grid.Column="12" HorizontalAlignment="Center" Background="{ Binding HSCommand, Converter={StaticResource BackGroundFilterByHsCommand}}" />
<TextBlock Text="{Binding Data_Str}" Grid.Column="14"/>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
<ListView.ContextMenu>
<ContextMenu x:Name="CMMenuCopy">
<MenuItem x:Name="MCICopyLine" Header="Copy Line" Click="MCICopyLine_Click" ></MenuItem>
<MenuItem x:Name="MCICopyText" Header="Copy Only Data Array" Click="MCICopyText_Click" ></MenuItem>
<MenuItem x:Name="MCIClear" Header="Clear" Click="MCIClear_Click"></MenuItem>
</ContextMenu>
</ListView.ContextMenu>
</ListView>
not working code multibinding:
<ListView x:Name="LVGuiCoreBus" ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.HorizontalScrollBarVisibility="Auto" MouseDown="LVGui_MouseDown" Grid.Row="1" >
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.Visibility>
<MultiBinding Converter="{StaticResource MultiValueConvertorVisibility}" UpdateSourceTrigger="PropertyChanged">
<Binding ElementName="Source" Path="Visibility" UpdateSourceTrigger="PropertyChanged"></Binding>
<Binding ElementName="Destination" Path="Visibility" UpdateSourceTrigger="PropertyChanged"></Binding>
<Binding ElementName="Module" Path="Visibility" UpdateSourceTrigger="PropertyChanged"></Binding>
<Binding ElementName="Controll" Path="Visibility" UpdateSourceTrigger="PropertyChanged"></Binding>
<Binding ElementName="Command" Path="Visibility" UpdateSourceTrigger="PropertyChanged"></Binding>
<Binding ElementName="HSCommand" Path="Visibility" UpdateSourceTrigger="PropertyChanged"></Binding>
</MultiBinding>
</Grid.Visibility>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="130"></ColumnDefinition>
<ColumnDefinition Width="10"></ColumnDefinition>
<ColumnDefinition Width="50"></ColumnDefinition>
<ColumnDefinition Width="10"></ColumnDefinition>
<ColumnDefinition Width="50"></ColumnDefinition>
<ColumnDefinition Width="10"></ColumnDefinition>
<ColumnDefinition Width="100"></ColumnDefinition>
<ColumnDefinition Width="10"></ColumnDefinition>
<ColumnDefinition Width="70"></ColumnDefinition>
<ColumnDefinition Width="10"></ColumnDefinition>
<ColumnDefinition Width="150"></ColumnDefinition>
<ColumnDefinition Width="10"></ColumnDefinition>
<ColumnDefinition Width="150"></ColumnDefinition>
<ColumnDefinition Width="10"></ColumnDefinition>
<ColumnDefinition Width="1*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding DateNTimeStr}" Foreground="Green" Grid.Column="0" />
<TextBlock Text="{Binding Source}" Foreground="{Binding Source,Converter={StaticResource CoreBusPanelModuleColorConverter}}" Grid.Column="2" Background="{ Binding Source, Converter={StaticResource BackGroundFilterConverterBySource}}" />
<TextBlock Text="{Binding Destination}" Foreground="{Binding Destination,Converter={StaticResource CoreBusPanelModuleColorConverter}}" Grid.Column="4" Background="{ Binding Destination, Converter={StaticResource BackGroundFilterConvertorByDestantation}}" />
<TextBlock Text="{Binding Module}" Grid.Column="6" HorizontalAlignment="Center" Background="{ Binding Module, Converter={StaticResource BackGroundFilterByModule}}" />
<TextBlock Text="{Binding Controll}" Grid.Column="8" Background="{ Binding Controll, Converter={StaticResource BackGRoundFilterByControll}}" />
<TextBlock Text="{Binding Command}" Grid.Column="10" HorizontalAlignment="Center" Background="{ Binding Command, Converter={StaticResource BackGroundFilterByCommand}}" />
<TextBlock Text="{Binding HSCommand}" Grid.Column="12" HorizontalAlignment="Center" Background="{ Binding HSCommand, Converter={StaticResource BackGroundFilterByHsCommand}}" />
<TextBlock Text="{Binding Data_Str}" Grid.Column="14"/>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
<ListView.ContextMenu>
<ContextMenu x:Name="CMMenuCopy">
<MenuItem x:Name="MCICopyLine" Header="Copy Line" Click="MCICopyLine_Click" ></MenuItem>
<MenuItem x:Name="MCICopyText" Header="Copy Only Data Array" Click="MCICopyText_Click" ></MenuItem>
<MenuItem x:Name="MCIClear" Header="Clear" Click="MCIClear_Click"></MenuItem>
</ContextMenu>
</ListView.ContextMenu>
</ListView>
public class MultiValueConvertorVisibility : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
bool x = System.Convert.ToBoolean(values[0]);
if (x)
{
return System.Windows.Visibility.Visible;
}
else
{
return System.Windows.Visibility.Collapsed;
}
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
The most important piece conceptually that you are missing is the IMultiValueConverter, because visibility is just one value, at the end of the day, you want your grid to be either visible or not, so you have to tell the multibinding how to compose your multiple values into one.
Here is an example of how to get multi-binding to work:
The Grid:
<Window x:Class="WpfApp1.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:local="clr-namespace:WpfApp1"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<local:MultiValueConverter x:Key="MyCustomConvertor"/>
</Window.Resources>
<Grid ShowGridLines="True">
<Grid.Visibility>
<MultiBinding Converter="{StaticResource MyCustomConvertor}" UpdateSourceTrigger="PropertyChanged">
<Binding Path="Visibility"/>
</MultiBinding>
</Grid.Visibility>
<Grid.RowDefinitions>
<RowDefinition Height="100"/>
<RowDefinition Height="100"/>
<RowDefinition Height="100"/>
</Grid.RowDefinitions>
</Grid>
The Viewmodel that you bind to:
using System.ComponentModel;
using System.Windows;
namespace WpfApp1
{
class VM : INotifyPropertyChanged
{
#region WPF integration properties
public event PropertyChangedEventHandler PropertyChanged;
// Create the OnPropertyChanged method to raise the event
protected void OnPropertyChanged(string name)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
#endregion
private Visibility _visibility = Visibility.Hidden;
public Visibility Visibility
{
get { return _visibility; }
set
{
_visibility = value;
OnPropertyChanged(nameof(Visibility));
}
}
}
}
And finally the MultiValueConverter to convert multiple visibility bindings into one:
using System;
using System.Linq;
using System.Windows;
using System.Windows.Data;
namespace WpfApp1
{
class MultiValueConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (values.Contains(Visibility.Collapsed))
{
return Visibility.Collapsed;
}
if (values.Contains(Visibility.Hidden))
{
return Visibility.Hidden;
}
return Visibility.Visible;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
Into the converter you could place any logic that you see fit, I just imposed a kind of hierarchy on the different visibility types.

change booleanToVisibilityConverter from code behind - wpf c #

<Page.Resources>
<ResourceDictionary>
<BooleanToVisibilityConverter x:Key="booleanToVisibilityConverter" x:Name="testTest" />
</ResourceDictionary>
</Page.Resources>
itemscontrol:
<Grid Grid.Row="1" Grid.ColumnSpan="2" Name="testName">
<ScrollViewer VerticalScrollBarVisibility="Hidden" PanningMode="Both">
<ItemsControl ItemsSource="{Binding Path=NextMeetingList}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Grid.Column="0" Grid.Row="0">
<Border x:Name = "myVariable" Grid.Column="0" Grid.Row="0" Margin="10" Height="30" Background="#A2C2E7" CornerRadius="5" BorderBrush="#A2C2E7">
<Grid Margin="8,0,8,0" Background="#A2C2E7">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"></ColumnDefinition>
<ColumnDefinition Width="1*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="30"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Foreground="White" FontWeight="Bold" FontSize="15" Margin="0,4,0,0" HorizontalAlignment="Left">month</TextBlock>
<TextBlock Grid.Row="0" Grid.Column="1" Foreground="White" FontWeight="Bold" FontSize="15" Margin="0,4,0,0" HorizontalAlignment="Right">1 Meeting</TextBlock>
</Grid>
</Border>
<Border Grid.Column="0" Grid.Row="0" Margin="10" Height="60" Background="GhostWhite" CornerRadius="3" BorderBrush="{Binding BorderColor}" BorderThickness="0,8,0,0">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="118"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="60"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" HorizontalAlignment="Left" FontSize="40" Margin="10,5,0,0" Style="{DynamicResource Lato-Semibold}" Text="{Binding endDate.Day}"/>
<TextBlock Grid.Row="0" Grid.Column="0" HorizontalAlignment="Left" FontSize="12" Margin="77,13,0,0" Height="Auto" Style="{DynamicResource Lato-Semibold}" Text="{Binding DayString}"/>
<TextBlock Grid.Row="0" Grid.Column="0" HorizontalAlignment="Left" FontSize="14" Margin="70,26,0,0" Height="Auto" Style="{DynamicResource Lato-Semibold}" Text="{Binding endDate.Hour}"/>
<TextBlock Grid.Row="0" Grid.Column="0" HorizontalAlignment="Left" FontSize="14" Margin="86,26,0,0" Height="Auto" Style="{DynamicResource Lato-Semibold}" Text=":"/>
<TextBlock Grid.Row="0" Grid.Column="0" HorizontalAlignment="Left" FontSize="14" Margin="90,26,0,0" Height="Auto" Style="{DynamicResource Lato-Semibold}" Text="{Binding MinuteString}"/>
<Border Grid.Row="0" Grid.Column="0" Width="1" BorderBrush="#BABABA" Height="40" Margin="115,-6,0,0" BorderThickness="1" HorizontalAlignment="Left"></Border>
<TextBlock Grid.Row="0" Grid.Column="1" HorizontalAlignment="Left" Text="{Binding subject}" FontWeight="Bold" FontSize="17" Margin="10,10,0,0"/>
<TextBlock Grid.Row="0" Grid.Column="1" Width="Auto" TextWrapping="Wrap" HorizontalAlignment="Left" Text="{Binding descr}" FontSize="10" Margin="20,27,150,0"/>
<TextBlock Grid.Row="0" Grid.Column="1" HorizontalAlignment="Right" Text="{Binding companyName}" FontSize="10" Margin="0,10,30,0"/>
<TextBlock Grid.Row="0" Grid.Column="1" HorizontalAlignment="Right" Text="sala del consiglio" FontSize="10" Margin="0,27,30,0"/>
<TextBlock Grid.Row="0" Grid.Column="1" HorizontalAlignment="Right" Text=">" FontSize="15" VerticalAlignment="Center" Margin="0,-5,10,0"/>
</Grid>
</Border>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</Grid>
Hello everyone , I should be able to make a grid Collapsed inside a ItemsControl in WPF .
The problem is that I can not understand how to use the booleanToVisibilityConverter from code behind .
Maybe I'm missing out on a glass of water but I can not connect how to do, if the name TestTest septum can not see it then the code-behind .
from code behind i don't see "myVariable"
To get hold of the converter from code-behind, you'd have to look it up in the Page's Resources dictionary. Do something like this in your Page class:
IValueConverter converter = this.Resources["booleanToVisibilityConverter"] as IValueConverter;
Giving the converter's resource entry a Name is not necessary; here you want to use the Key. Also, converters are normally used with XAML bindings -- if you want one in code, you can just instantiate one:
IValueConverter converter = new BooleanToVisibilityConverter();
Common usage goes something like this:
<Window.Resources>
<ResourceDictionary>
<BooleanToVisibilityConverter x:Key="Converter" />
</ResourceDictionary>
</Window.Resources>
<Grid Visibility="{Binding Display, Converter={StaticResource Converter}}">
...
</Grid>
Code-behind, using the window class itself as the data context:
public partial class MainWindow
{
public bool Display { get; set; };
public MainWindow()
{
InitializeComponent();
DataContext = this; // For the binding
Display = true;
}
}
Okay, one more, this time without data binding or converter:
<Grid x:Name="myGrid">
...
</Grid>
Code-behind:
public partial class MainWindow
{
public MainWindow()
{
InitializeComponent();
myGrid.Visibility = Visibility.Visible;
}
}
The above doesn't explain why the OP couldn't reference "myVariable" from code-behind. That's because it's in a template, which is instantiated (dynamically) once per item in the collection.
It's still possible to get at it from code -- dynamically. For example, this XAML uses a DataTemplate:
<ItemsControl ItemsSource="{Binding Names}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Grid x:Name="innerGrid" Loaded="OnGridLoaded" DataContext="{Binding Name, Mode=OneWay}">
<TextBox Text="{Binding Path=., Mode=OneWay}" />
</Grid>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
The following code-behind lets us reach into the template and make "innerGrid" disappear selectively:
public class Data
{
public string Name { get; }
public Data(string name)
{
Name = name;
}
}
public partial class MainWindow
{
public Data[] Names { get; } = { new Data("Hello"), new Data("World") };
public MainWindow()
{
InitializeComponent();
DataContext = this;
}
private void OnGridLoaded(object sender, RoutedEventArgs e)
{
Grid outerGrid = sender as Grid;
Grid innerGrid = outerGrid?.FindName("innerGrid") as Grid;
if (innerGrid != null)
{
string name = innerGrid.DataContext as string;
if (name == "Hello")
{
innerGrid.Visibility = Visibility.Collapsed;
}
}
}
}
(To make the string easily accessible I bound the Data object to the "innerGrid" DataContext.)

How to bind buttons in ListView DataTemplate to Commands in ViewModel? (MVVMLight)

I have a list view with following code:
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<ListBox x:Name="allToDoItemsListBox"
ItemsSource="{Binding AllToDoItems,Mode=OneWay}"
Margin="12,0,12,0"
Width="440"
ItemTemplate="{StaticResource ToDoListBoxItemTemplate}" />
</Grid>
The datatemplate is as follows :
<phone:PhoneApplicationPage.Resources>
<DataTemplate x:Key="ToDoListBoxItemTemplate">
<Grid HorizontalAlignment="Stretch" Width="420">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="100" />
</Grid.ColumnDefinitions>
<CheckBox
IsChecked="{Binding IsComplete, Mode=TwoWay}"
Grid.Column="0" VerticalAlignment="Top"/>
<TextBlock
Text="{Binding ItemName}"
FontSize="{StaticResource PhoneFontSizeLarge}"
Foreground="Gray"
Grid.Column="1" Grid.ColumnSpan="2"
VerticalAlignment="Top" Margin="-36, 12, 0, 0"/>
<Button
Grid.Column="3"
x:Name="deleteTaskButton"
BorderThickness="0"
Margin="0, -18, 0, 0"
Command="{Binding Path=DeleteCommand}" CommandParameter="{Binding}"/>
<Image
Source="/Images/appbar.delete.rest.png"
Height="75"
Width="75"/>
</Grid>
</DataTemplate>
</phone:PhoneApplicationPage.Resources>
I tried to bind the Button Command "DeleteCommand" to a ICommand in ViewModel but it failed what should i do?
The Code in ViewModel is :
public ICommand DeleteCommand { get; private set; }
In the ViewModel Construct :
DeleteCommand = new RelayCommand<object>(Delete);
And The delete method :
private void Delete(object obj)
{
ToDoItem newToDoItem = obj as ToDoItem;
DeleteToDoItem(newToDoItem);
}
I need to pass the item to DeleteToDoItem() method as parameter when the corresponding delete button of each item in the list is pressed but the command does not fire here what should i do?
In your ViewModel you want to pass a ToDoItem to your Delete command.
DeleteCommand = new RelayCommand<ToDoItem>(DeleteToDoItem);
And your DataTemplate's DataContext is different from the ListView's.
<Button Command="{Binding ElementName=allToDoItemsListBox,
Path=DataContext.DeleteCommand}"
CommandParameter="{Binding}" />
That should do it.

Binding items using multiple selection mode ListBox?

Here is my problem i need to solve.
My data content is in DemoList class:
NOTICE: DemoHeader object contains a ObservableCollection of DemoItem objects, and DemoList object contains ObservableCollection of DemoHeader objects
public enum Type
{
article,
product,
material
}
public class DemoHeader
{
private ObservableCollection<DemoItem> _items;
public ObservableCollection<DemoItem> Items
{
get { return _items; }
set { _items = value; }
}
public DemoHeader(string document)
{
this._salesOrder = document;
_items = new ObservableCollection<DemoItem>();
}
private string _salesOrder;
public string SalesOrder
{
get { return _salesOrder; }
set { _salesOrder = value; }
}
}
public class DemoItem
{
public DemoItem(string name, Type type)
{
this._name = name;
this._type = type;
}
private Type _type;
public Type Type
{
get { return _type; }
set { _type = value; }
}
private string _name;
public string Name
{
get { return _name; }
set { _name = value; }
}
}
public class DemoList : ObservableCollection<DemoHeader>//, ICollectionView
{
public DemoList()
{
DemoHeader dd = new DemoHeader("Doc-1");
dd.Items.Add(new DemoItem("T-1", Type.article));
dd.Items.Add(new DemoItem("M-1", Type.material));
DemoHeader dd2 = new DemoHeader("Doc-2");
dd2.Items.Add(new DemoItem("P-1", Type.product));
dd2.Items.Add(new DemoItem("P-2", Type.product));
this.Add(dd);
this.Add(dd2);
}
}
XAML:
NOTICE: I have 4 CollectionViewSource for each ListBox.
<Window x:Class="WuZet.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:c="clr-namespace:WuZet"
Title="WuZet" WindowStartupLocation="CenterScreen" ResizeMode="CanResize" Loaded="window_loaded" Background="#ECE9D8" WindowStyle="ToolWindow" Icon="/WuZet;component/Images/ksi_ikona.ico" Topmost="True" WindowState="Maximized" SizeToContent="WidthAndHeight">
<Window.Resources>
<CollectionViewSource x:Key="list" Source="{Binding}"></CollectionViewSource>
<CollectionViewSource x:Key="wares" Source="{Binding Source={StaticResource list}, Path=Items}" Filter="wareFilter"></CollectionViewSource>
<CollectionViewSource x:Key="materials" Source="{Binding Source={StaticResource list}, Path=Items}" Filter="materialFilter"></CollectionViewSource>
<CollectionViewSource x:Key="products" Source="{Binding Source={StaticResource list}, Path=Items}" Filter="productFilter"></CollectionViewSource>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="80"></RowDefinition>
<RowDefinition Height="20"></RowDefinition>
<RowDefinition Height="200"></RowDefinition>
<RowDefinition Height="50"></RowDefinition>
<RowDefinition Height="200"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<StackPanel Grid.Row="0" Grid.ColumnSpan="2" Margin="5,5,5,5">
<TextBox/>
<Button Content="ok" Margin="0,5,0,0" HorizontalAlignment="Stretch" Height="30" Width="150" Click="Button_Click"/>
</StackPanel>
<StackPanel Grid.RowSpan="2" Grid.Column="2">
<ListBox Name="orders" IsEnabled="{Binding ElementName=check, Path=IsChecked}" Margin="85,5,85,5" Height="70" ItemsSource="{Binding Source={StaticResource list}}" DisplayMemberPath="SalesOrder"/>
<CheckBox Name="check" HorizontalAlignment="Center" Content="Wybierz zamówienie" IsChecked="False"/>
</StackPanel>
<GroupBox Header="Wares" Grid.Row="2" Grid.Column="0">
<ListBox Name="lbWares" ItemsSource="{Binding Source={StaticResource wares}}" >
<ListBox.ItemTemplate>
<DataTemplate>
<!--<StackPanel Orientation="Horizontal">-->
<TextBlock Text="{Binding Path=Name}"></TextBlock>
<!--<TextBlock Text="{Binding ZaE_TwrKod}" />
<TextBlock Text=", " />
<TextBlock Text="{Binding ZaE_Ilosc}" />
<TextBlock Text=", " />
<TextBlock Text="{Binding ZaE_TwrNazwa}" />-->
<!--</StackPanel>-->
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</GroupBox>
<GroupBox Header="Materials" Grid.Row="2" Grid.Column="1">
<ListBox Name="lbMaterials" ItemsSource="{Binding Source={StaticResource materials}}">
<ListBox.ItemTemplate>
<DataTemplate>
<!--<StackPanel Orientation="Horizontal">-->
<TextBlock Text="{Binding Path=Name}"/>
<!--<TextBlock Text=", " />
<TextBlock Text="{Binding ZaE_Ilosc}" />
<TextBlock Text=", " />
<TextBlock Text="{Binding ZaE_TwrNazwa}" />-->
<!--</StackPanel>-->
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</GroupBox>
<GroupBox Header="Products" Grid.Row="2" Grid.Column="2">
<ListBox Name="lbProducts" ItemsSource="{Binding Source={StaticResource products}}">
<ListBox.ItemTemplate>
<DataTemplate>
<!--<StackPanel Orientation="Horizontal">-->
<TextBlock Text="{Binding Path=Name}"/>
<!--<TextBlock Text=", " />
<TextBlock Text="{Binding ZaE_Ilosc}" />
<TextBlock Text=", " />
<TextBlock Text="{Binding ZaE_TwrNazwa}" />
</StackPanel>-->
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</GroupBox>
</Window>
DemoList object is binding to CollectionViewList x:Key=list.
Here is my buisiness logic i need to implement:
If checkbox is marked i need to return selected ListBoxItem to the
corresponding containers [wares, products, materials] - this logic is
working
If checkbox is unmarked i need to return ALL items
[ObservableCollection] of ALL headers to the corresponding
containers [wares, products, materials]
I'm stuck right here, can anyone suggest me a solution?
--- 2013-11-04 20:38
Sry for misunderstanding, and for my bad english.
I uploaded some screen to be more clear.
http://imgur.com/UowQrRP
As you see on the screen i need to implement behavior for checkbox.
When it is unchecked each DemoItem object must be display in one of 3 containers.
Each container is bind to CollectionViewSource.

How to set tooltip with many rows for each (dynamic) listbox item in Silverlight

I would like to set in Silverlight for each item in a ListBox a tooltip with many rows.
In XAML i have a listbox and a button:
<ListBox Height="100" HorizontalAlignment="Left" Margin="24,136,0,0" Name="listBox1" VerticalAlignment="Top" Width="109" ItemsSource="{Binding}">
<Button Content="Add" Name="button_add" VerticalAlignment="Top" Width="118" Click="add_Click">
in c#
private void button_add_Click(object sender, RoutedEventArgs e)
{
ObservableCollection<Person> obs1 = new ObservableCollection<Person>();
obs1.Add(new Person(){Name="Name1", Age=1});
obs1.Add(new Person(){Name="Name2", Age=2});
listBox1.ItemsSource = obs1;
// This Line of Code MUST NOT BE USED!! listBox1.DisplayMemberPath = "Name";
}
public class Person
{
public String Name { get; set; }
public int Age { get; set; }
public override string ToString()
{
return Name;
}
}
I would like to show for each item the Age as my tooltip.
Edit: Ok, this is the Solution for showing only AGE as tooltip. That is one Line/Row.
<ListBox Height="100" HorizontalAlignment="Left" Margin="24,136,0,0" Name="listBox1" VerticalAlignment="Top" Width="109" ItemsSource="{Binding}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" ToolTipService.ToolTip="{Binding Age}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
But what if i want to show a Tooltip with 2 Lines? something like:
Name: Name1
Age: 1
Edit: 3 rows, 2 columns. i also added public String Comment { set; get; } to class Person
<ListBox Height="100" HorizontalAlignment="Left" Margin="24,136,0,0" Name="listBox1" VerticalAlignment="Top" Width="109" ItemsSource="{Binding}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<ToolTipService.ToolTip>
<ToolTip>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="20"></RowDefinition>
<RowDefinition Height="20"></RowDefinition>
<RowDefinition Height="40"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="80"/>
<ColumnDefinition Width="250"/>
</Grid.ColumnDefinitions>
<TextBlock Text="Name: " Grid.Row="0" Grid.Column="0" />
<TextBlock Text="{Binding Name}" Grid.Row="0" Grid.Column="1"/>
<TextBlock Text="Age: " Grid.Row="1" Grid.Column="0"/>
<TextBlock Text="{Binding Age}" Grid.Row="1" Grid.Column="1"/>
<TextBlock Text="Comment: " Grid.Row="2" Grid.Column="0"/>
<TextBlock Text="{Binding Comment}" Grid.Row="2" Grid.Column="1" TextWrapping="Wrap" />
</Grid>
</ToolTip>
</ToolTipService.ToolTip>
<TextBlock Text="{Binding Name}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
But there is stil a problem. The comment can be short or long, so i would like to make the ROWS/LINES/SPACE for Comment to be variable or else Text is cut off.
You can use any controls for tooltip content:
<ToolTipService.ToolTip>
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding Name}" />
<TextBlock Text="{Binding Age}" />
</StackPanel>
</ToolTipService.ToolTip>
Other possibility would be to use a converter, that returns the Name and Age separated by \r\n.

Categories

Resources