In WPF, I am trying to disable combo boxes inside a telerik:GridViewDataColumn based on the IsComboBoxEnabled property of my ViewModel. If I set IsEnabled=false from XAML, it works and the combo box is disabled. However, when I bind IsEnabled to a value on my viewmodel, it is always enabled even when the value is set to false.
<telerik:GridViewDataColumn>
<telerik:GridViewColumn.CellTemplate>
<DataTemplate>
<telerik:RadComboBox SelectedValue="{Binding SomeSelectedValue}"
ItemsSource="{Binding SomeItemsSource}"
IsEnabled="{Binding IsComboBoxEnabled, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</DataTemplate>
</telerik:GridViewColumn.CellTemplate>
</telerik:GridViewDataColumn>
public bool IsComboBoxEnabled
{
get
{
return _isComboBoxEnabled;
}
set
{
_isComboBoxEnabled = value;
RaisePropertyChanged("IsComboBoxEnabled");
}
}
The issue was due to me setting the IsComboBoxEnabled property from the viewmodel of the datagrid instead of the viewmodel of the individual record.
Related
I have a ComboBox in a DataTemplate which is being selected by a cell template selector in a DataGrid.
How do I set the SelectedItem to zero when the ComboBox is bound to its ItemsSource? There's often just one item and I want it to appear immediately instead of having to be selected by the user.
My DataGrid column looks like this:
<DataGridTemplateColumn Header="Qty Avl">
<DataGridTemplateColumn.CellTemplateSelector>
<selectors:PartAvailableSelector StrTemplate="{StaticResource PartAvailableAtStrTemplate}">
<selectors:PartAvailableSelector.NetTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding AltLocations}"
DisplayMemberPath="Name"
SelectedItem="0"
/>
</DataTemplate>
</selectors:PartAvailableSelector.NetTemplate>
</selectors:PartAvailableSelector>
</DataGridTemplateColumn.CellTemplateSelector>
</DataGridTemplateColumn>
My selector has DataTemplate properties, just because it's easier. I inlined the NetTemplate template for this post. I normally have it in my window resources.
SelectedItem will the hold entire object from ItemsSource, to set the 0 item as selected you need to set SelectedIndex="0" or in ViewModel u need to bind SelectedItem="{Binding SLocation}" to AltLocations[0]
<ComboBox ItemsSource="{Binding AltLocations}"
DisplayMemberPath="Name"
SelectedIndex="0"
/>
Or
<ComboBox ItemsSource="{Binding AltLocations}"
DisplayMemberPath="Name"
SelectedItem="{Binding SLocation}"
/>
Vm
private Location sLocation
public Location SLocation
{
get { return sLocation; }
set
{
sLocation= value;
OnPropertyChanged(new PropertyChangedEventArgs("SLocation"));
}
}
//Ctor
SLocation=AltLocations[0];
I have a wpf project with a ComboBox. The items there inside are filled in dynamically. So it is bound to a model which contains a Label and a Command.
If the User selects an item in the Dropdown / ComboBox the Command should be executed. I tried it with a DataTemplate containing a TextBlock and a Hyperlink for the Command. But the Command will only execute if a select the Label (Hyperlink) and not if I click on the whole item.
<ComboBox ItemsSource="{Binding Path=States}" SelectedItem="{Binding CurrentState}" >
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock>
<Hyperlink Command="{Binding Command}" TextDecorations="None" Foreground="Black">
<TextBlock Text="{Binding Path=Label}"/>
</Hyperlink>
</TextBlock>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
So the question is now, how can I bind my Command to a ComboBoxItem?
A ComboBoxItem has no Command property but you could execute the command from the setter of the CurrentState property:
private State _currentState;
public State CurrentState
{
get { return _currentState; }
set
{
_currentState = value;
if (_currentState != null)
{
_currentState.Command.Execute(null);
}
}
}
This property will be set whenever you select an item in the ComboBox. The other option would be to handle the SelectionChanged event in the view.
There is a UserControl which contains the bindings like below.
<TextBox Margin="5" Padding="0" IsReadOnly="True" Background="Transparent" BorderThickness="0" TextWrapping="Wrap" IsTabStop="False" FontSize="{DynamicResource TitleFontSize}" Text="{Binding ErrorTitle, Mode=OneWay}" />
it is bound by stack panel with name of GenericErrorControl and binding is as
<Visibility="{Binding IsShown, Mode=OneWay, Converter={StaticResource BoolToVis}, FallbackValue=Collapsed}">
Above control is added to one of view as below.
<views:GenericErrorControl Grid.Row="8" DataContext="{Binding GenericErrorControl, Mode=OneWay}" VerticalAlignment="Top/>
The problem is that user control is not appearing in the window after. In my viewmodel creating object i'm setting the value of IsShown but its not appearing. Kindly help and let me know if any other details needed.
It means that the binding is failing ie the fallback value is used from above code.
Things to do :
Ensure that your ViewModel inherits from the base class BindableBase ie it somehow implements the INotifyPropertyChanged interface and on property change, the PropertyChanged event is fired.
ie You have something similar to this in your view model.
private bool _IsShown;
public bool IsShown
{
get { return _IsShown; }
set { SetProperty(ref _IsShown, value); }
}
Double check your converter or post code here.
I want to bind IsEnable property of button to variable. Button is added inside data grid. Data Grid is located inside user control.
Below code is not working.
<DataGridTemplateColumn Header="Start" >
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button x:Name="Start_Button"
DataContext="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type UserControl}},Path=DataContext}"
IsEnabled="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type DataGrid}},Path=IsStartButtonEnable}"
Command="{Binding StartCommand}">START
</Button>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
Model contains-(ServerModel.cs)
private bool _isStartButtonEnable = false;
public bool IsStartButtonEnable
{
get
{
return _isStartButtonEnable;
}
set
{
_isStartButtonEnable = value;
this.OnPropertyChanged("IsStartButtonEnable");
}
}
View Model(ServerViewModel.cs) Contains -
public static ObservableCollection<ServerModel> DataGridServerList { get; set; }
UserControl (ServerUserControl.cs) contains -
this.DataContext = new ServerViewModel();
Requirements - UserControl contains 3 buttons-Create, Start and Stop. User clicks on Create Button. If Create commnd gets success, then Start button gets enabled.Then user will click on Start button. If start commnd gets executed successfully, then Stop button gets enabled and so on.
<DataGridTemplateColumn Header="Start" >
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button x:Name="Start_Button"
IsEnabled="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type UserControl}},Path=DataContext.IsStartButtonEnable}"
Command="{Binding StartCommand}">START
</Button>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
I am using the DataContext of the UserControl directly and not that of the DataGrid.
In your case, indeed, the DataContext of the Button will be set to each item in the DataGrid. In order to access the property on your UserControl you need this change. Further more, you don't need to set the DataContext again so i removed that line.
You have two possibilities in my opinion. Either set the flag in the ViewModel and will be accessible by all Buttons through the Relative Source syntax or if you have it in the Model, you will have a flag for each row in the DataGrid. In either case you have the response:
If it is in the Model, set the DataGrid ItemsSource to your ObservableCollection and use
IsEnabled = {Binding IsStartButtonEnable }
2.If it is in the ViewModel, use
IsEnabled="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type UserControl}},Path=DataContext.IsStartButtonEnable}"
I don't see other option but if you want it available for all Buttons in the DataGrid you have to set it in the ViewModel.
I have code like this:
<ListBox ItemsSource="{Binding}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock>Some Other Stuff Here</TextBlock>
<ComboBox ItemsSource="{Binding}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
The problem is, every time the outside ListBox.SelectedItem gets changed, the ComboBoxes inside it would change their SelectedIndex to -1. Which means if I click "Some Other Stuff Here" (unless the ListBoxItem it is in is selected), all the comboboxes' selection get cleared.
How do I overcome this? Thx!
Presumably your combobox is bound to something like an ObservableCollection - try exposing an instance of ICollectionView instead:
class DataSource
{
// ...
public ObservableCollection<string> MyData { get; private set; }
public ICollectionView MyDataView
{
get
{
return CollectionViewSource.GetDefaultView(this.MyData);
}
}
}
You can then bind your combobox with:
<ComboBox ItemsSource="{Binding MyDataView}" IsSynchronizedWithCurrentItem="True" />
This means that the 'selected item' for each data source is stored in the ICollectionView object instead of within the combobox, which should mean that it is persisted when the ListBox SelectedItem changes