Updating WPF XAML Combobox selecteditem from powershell - wpf

I'm just simply trying to change the selected item on a combobox drop down from powershell. Whenever I use:
$dg_Servers.Items[0].cbox_Disk.SelectedItem = 88
I receive the error:
"...cannot be found on this object. Verify that the property exists and can be set."
Here's my XAML:
DataGridTemplateColumn Header="DiskC" Visibility="Visible" Width="61" >
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox
ItemsSource="{Binding Path=cbox_DiskC}"
SelectedItem="{Binding Path=cbox_DiskD, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
</ComboBox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
I'm not sure what I'm missing here.. seems like this should be super easy. System.Windows.Forms makes this a no brainer to accomplish.
EDIT - adding the powershell side:
$row= New-Object NewRow -Property #{ServerName = ""; cbox_DiskC = (80..250); cbox_DiskD = (50..250); cbox_DiskE = (1..250); cbox_DiskF = (1..250); cbox_DiskG= (1..250); cbox_Mem=(1..16); cbox_CPU=(1..8); cbox_OSSpec = $Options_OSSpecs; cbox_Template = $Options_Templates; cbox_VLAN = $Options_VLAN ; cbox_Folder = $Options_Folders }
$itemsource = New-Object -TypeName System.Collections.ObjectModel.ObservableCollection[object] -ArgumentList #($row)
$dg_Servers.ItemsSource = $itemsource
I read this morning that you have to use an observablecollection in order for the UI to be notified of a change and refresh.. but I'm still not having any luck. I'm only using one thread so maybe that's the issue?
I was trying to change the combobox's drop down selection with another buttons click event.
$btn_Validate.Add_Click({$dg_Servers.SelectedItems[0].cbox_DiskC = 88})
But as I said, when I click the button on the UI nothing changes and the selection remains the same.

You should set the cbox_DiskD source property that is bound to the SelectedItem property of the ComboBox:
$dg_Servers.Items[0].cbox_DiskD = 88

Probably not the right way to do it but at this point I've spent too much time trying to figure out a better way :)
I had to bind to a different element in my class. Making them different allows me to keep all my items in the dropdown AND select a specific one. Otherwise if I keep them the same, all of my items disappear and it's set to 88. (NOTE: cbox_DiskC as the itemsource and cbox_DiskC_selected as the selecteditem below)
<DataGridTemplateColumn Header="DiskC" Visibility="Visible" Width="61" >
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox
ItemsSource="{Binding Path = cbox_DiskC}"
SelectedItem="{Binding Path=cbox_DiskC_selected, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
</ComboBox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
Once I did that, in the add_click I basically $nulled the itemsource, and re-added it which forces my GUI to refresh.
$btn_Validate.Add_Click({$row.cbox_DiskC_selected = 88; $dg_Servers.ItemsSource = $null; $dg_Servers.ItemsSource = $itemsource})
Later on I'll make a function that does the refresh to clean it up a bit.

Related

Toggle between combo-boxes and persist label in combo-box in WPF(XAML)

I am new to WPF and unable to implement the below scenario :
Three drop down boxes side by side. I have tried using Combo Box. I have tried to explain the problems with the help of an image
Example : (refer image)
I want to select any one - name/school/email. Say I select Name1 , then I should not be able to choose any of the other two dropdowns - School/Email.However, in my implementation I am still able to select values from the other dropdowns as well.
If I change my mind and move to the School dropdown and leave the Name dropdown, the Name dropdown should change the value from Name1(which was selected in Step 1) to Name(which is the title of that button), However, in my implementation both the selections - Name1 and School1 are persisting.
I tried implementing this with the help of these two posts and the nearest I could get was as I mentioned in the example above : How to display default text "--Select Team --" in combo box on pageload in WPF? and Name on combobox in WPF
PS : Name/School/ Email are NOT watermarks. They are the title of the button which is there by default as you land on that page/window.
Any help/resources is appreciated.
You can use the selection changed event of the comboboxes to set the text of each if you are going to code in code-behind:
<StackPanel Grid.Row="1" Orientation="Horizontal">
<ComboBox x:Name="cmbName" ItemsSource="{Binding NameList, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Text="Name"
SelectionChanged="cmbName_SelectionChanged" MinWidth="80" Margin="10" IsEditable="True" IsReadOnly="True"/>
<ComboBox x:Name="cmbSchool" ItemsSource="{Binding SchoolList, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Text="School"
SelectionChanged="cmbSchool_SelectionChanged" MinWidth="80" Margin="10" IsEditable="True" IsReadOnly="True"/>
<ComboBox x:Name="cmbEmail" ItemsSource="{Binding EmailList, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Text="Email"
SelectionChanged="cmbEmail_SelectionChanged" MinWidth="80" Margin="10" IsEditable="True" IsReadOnly="True"/>
</StackPanel>
In the selection changed of the Name combobox do the following:
private void cmbName_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if(cmbName.SelectedItem != null)
{
cmbSchool.SelectedItem = null;
cmbSchool.Text = "School";
cmbEmail.SelectedItem = null;
cmbEmail.Text = "Email";
}
}
Do the same for each of the other comboboxes; just change the combobox names respectively.
If you are using MVVM, then bind the SelectedItem and the Text property of each of the combobox and write a common method which sets the selected items to null and also the text property inside the setter of each of the bound SelectedItems respectively.

MVVM WPF - ComboBox two way binding inside ItemsControl

I am working on this problem for about a day now.
For some reason I am unable to TwoWay bind a value to a ComboBox if it is inside a ItemsControl. Outside works just fine.
I have an ObservableCollection of int? in my ViewModel:
private ObservableCollection<int?> _sorterExitsSettings = new ObservableCollection<int?>();
public ObservableCollection<int?> SorterExitsSettings
{
get { return _sorterExitsSettings; }
set
{
if (_sorterExitsSettings != value)
{
_sorterExitsSettings = value;
RaisePropertyChanged("SorterExitsSettings");
}
}
}
My XAML:
<ItemsControl ItemsSource="{Binding SorterExitsSettings}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding RelativeSource={RelativeSource AncestorType=ItemsControl}, Path=DataContext.ScanRouter.Stores}"
SelectedValue="{Binding Path=., Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" DisplayMemberPath="name" SelectedValuePath="id" IsEditable="True" />
</DataTemplate>
</ItemsControl.ItemTemplate>
So the ComboBox is populated with a list of stores. It works fine so far.
The ObservableCollection SorterExitsSettings even has some values set which are shown in the displayed ComboBoxes. So setting the SelectedValue also works.
However when I change a selection, SorterExitsSettings wont change. While when I implement the ComboBoxes(100) without an ItemsControl it suddenly works fine.
<ComboBox ItemsSource="{Binding ScanRouter.Stores}" DisplayMemberPath="name" SelectedValuePath="id" IsEditable="True" SelectedValue="{Binding SorterExitsSettings[0], Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
Even better when I implement the ComboBoxes using the ItemsControl and also the example ComboBox shown above. When I change the single ComboBox's value it will change the value of the ComboBox inside the ItemsControl, but not the other way around.
Did somebody encounter this problem before?
My guess was that the ItemsControl doesn't like the fact that I am binding my selected value to an item in a list. However when I bind directly to a ViewModel property(Store) it also doesn't work.
I also tried using SelctedItem instead of SelectedValue and populate the ObservableCollection with Store objects instead of int?.
The problem is that you're binding your ComboBox's SelectedValue directly to the collection elements which are type int ?. This won't work, binding targets have to be properties. Try wrapping your int ? values in a class and expose the value as a property of that class with a getter and setter, i.e. something like this:
private ObservableCollection<Wrapper> _sorterExitsSettings = new ObservableCollection<Wrapper>();
... etc...
And:
public class Wrapper
{
public int? Value {get; set;}
}
And finally:
<ComboBox ... SelectedValue="{Binding Path=Value, Mode=TwoWay...
Post back here if you still have problems.

WPF Datagrid selecteditem = null in MVVM

I'm trying to work with a datagrid using the MVVM pattern. The problem is that whenever I change the VM property which is binded to SelectedItem to null, the View doesn't "deselect" the currently selected item. This is my binding in xaml:
<DataGrid Grid.Column="0" Grid.Row="0"
ItemsSource="{Binding Path=Users}"
AutoGenerateColumns="False"
CanUserAddRows="False"
IsReadOnly="True"
SelectedItem="{Binding Path=SelectedUser, Mode=TwoWay}">
The SelectedItem binding works from the view to the VM thus in the SelectedUser property I always have the selected object. The problem is that in the VM I'm doing some stuff which sometimes changes the SelectedUser property to null so I would expect the datagrid to deselect the row as well. Instead, it remains selected and if I try to click on the same row, the property doesn't update. If I click on any other row, the property changes as expected.
Is there a way to make the datagrid deselect if it's binded property is set to null? Also I'm looking for a MVVM solution as I don't want to write code behind. I can solve this by writing code behind so don't waste time offering such solutions :)
l.e.: this is my property in the VM:
public RPLUser SelectedUser
{
get
{
return selectedUser;
}
set
{
selectedUser = value;
OnPropertyChanged("SelectedUser");
}
}
Thanks in advance!
I recommend to check the Output Window in visual studio and see if any Binding is failing.
Are you sure when you select something, the selection updates into the SelectedUser property?
Did u put a breakpoint in setter of SelectedUser and see that it is hitting when you select something on the datagrid?
The reasons for this Binding to break could be many ...
SelectedUser is of different type than individual Users.
SelectedUser does not match by reference with any items in Users.
How and where are you setting null?
The following code in my case works perfectly fine...
<tk:DataGrid MaxHeight="200" AutoGenerateColumns="False"
ItemsSource="{Binding}"
SelectedItem="{Binding MySelItem,
ElementName=MyDGSampleWindow,
Mode=TwoWay}"
IsReadOnly="True">
<tk:DataGrid.Columns>
<tk:DataGridTextColumn Header="Key"
Binding="{Binding Key,
Mode=OneWay}"/>
<tk:DataGridTextColumn Header="Value"
Binding="{Binding Value,
Mode=OneWay}"/>
</tk:DataGrid.Columns>
</tk:DataGrid>
When I set MyDGSampleWindow.MySelItem as null, the datagrid propertly deselects. Perhaps you might need to give us more input on how are you actually setting the value as null.
Did you try setting IsSynchronizedWithCurrentItem="True" in the xaml properties for the DataGrid? AFAIK, this will allow you to unselect it by setting the SelectedUser to null.
I cannot test it at the moment, but you could also try to add this in the setter of your property:
set
{
selectedUser = value;
OnPropertyChanged("SelectedUser");
ICollectionView collectionView = CollectionViewSource.GetDefaultView(Users);
collectionView.MoveCurrentTo(selectedUser);
}
(For ICollectionView to do anything, you will need to have IsSynchronizedWithCurrentItem set)
Like I said, I cannot test this right now. Also, the setter of the property is probably not the best place to put it. Maybe create an event handler for the PropertyChangedevent locally and put that logic there.
Let me know if it helps, else I'll see if I can run a short test...
Yeah may need to add the XAML UpdateSourceTrigger to update the UI.
SelectedItem="{Binding SomeProperty, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
The DataGrid will not Deselect it automatically as DataGridRow's IsSelected property should be set to False.
You can do that by Setting a style on DataGrid.. like
<Style x:Key="dataGridRowStyle"
BasedOn="{StaticResource {x:Type WPFToolkit:DataGridRow}}"
TargetType="{x:Type WPFToolkit:DataGridRow}">
<Setter Property="IsSelected" Value="{Binding Path=IsSelected}" />
</Style>
The IsSelected property should be the of the object i.e in your case RPLUser should have a property Isselected
Then before you set the SelectedUser to null... just do SelectedUser.IsSelected=False
And dont forget to attach this style to the DataGridRowStyle in Datagrid
I am using WPFToolkit you can modify the style if you are targetting .NET 4.0

Silverlight Telerik GridViewComboBoxColumn problem on Insert

My scenario:
I have a Telerik Silverlight RadGridView With some columns, and one of them is
<telerik:RadGridView x:Name="Grid1" DataContext="{StaticResource ViewModelDailyReport}" IsSynchronizedWithCurrentItem="True" ScrollMode="RealTime" AutoGenerateColumns="false" ItemsSource="{Binding LogBookItems}" IsReadOnly="false" Visibility="Visible" >
[...]
<telerik:GridViewComboBoxColumn
Header="My Activity"
DataMemberBinding="{Binding Activity.ID, Mode=TwoWay}"
SelectedValueMemberPath="ID"
DisplayMemberPath="Name"
ItemsSource="{StaticResource ViewModelActivities}">
</telerik:GridViewComboBoxColumn>
[...]
So I Have a TwoWay binding on a Collection of Items in a ViewModel.
All works fine, except when I insert a new item (with RadGrid BeginInsert command): when user chooses an item from the dropdown, it is always blank in the cell...
The bound collection has a new item (on insert event), but there is no way to bind the newly added item with combobox.
What is the trick?
Thanks
Make sure you have a default constructor in the LogBookItem class.
In the default constructor, you can initialize your default values and also create a new Activity instance, since you are binding to it's ID.
public LogBook()
{
//initialize default values
this.CreationDate = DateTime.UtcNow;
this.Activity = new Activity(); //Activity.ID will equal 0
}

Silverlight Gridcolumn Collapse Visibility in code

I'm having a small problem.
I have this grid with a column:
<data:DataGrid ColumnHeaderStyle="{StaticResource headerStyle}" Foreground="#234BC3" AutoGenerateColumns="False" Name="protocollenBAMDataGrid" LoadingRow="myDataGrid_LoadingRow" SelectionChanged="DataGrid_SelectionChanged">
<data:DataGrid.Columns>
<data:DataGridTemplateColumn Header="Resend" x:Name="ResendColumn">
<data:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button Content="Resend" Tag="{Binding MsgID}" Foreground="#234BC3" Click="dataGridHL7_Click"></Button>
</DataTemplate>
</data:DataGridTemplateColumn.CellTemplate>
</data:DataGridTemplateColumn> ...
If i set the visibility of the "ResendColumn" to collapsed, it works fine.
However I need to do this in code, so I tried doing this in the loading event:
ResendColumn.Visibility = Visibility.Collapsed;
And it gives me a nullref exception:
Object reference not set to an
instance of an object.
I don't understand why?
I get the same behaviour in SL 4. I guess it is related to the column not being a UIElement and thus instantiated by the DataGrid itself (not by the usual stuff happening in InitializeComponent).
I had to access the columns through the Columns property of the DataGrid. And there, setting the visibility works.

Resources