I have a grid and each row (300 of them) consists of "string | string | int | string | check." If for example I click on the checkbox in row 7, nothing out of the ordinary happens. But if I click another checkbox on another row, I may get 10 other rows with their checkboxes checked, but these other checkboxes arent executing the code associated with them.
<DataGridTemplateColumn Width="*" Header="Add">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox Checked="CheckBox_Checked" Unchecked="CheckBox_Unchecked"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
It's because row visuals are reused. You could set <DataGrid EnableRowVirtualization="False"... but that will have a huge performance impact if there are many rows. A better solution is to use a ViewModel to store the check state. Then bind the value to the ViewModel <CheckBox IsChecked="{Binding MyBoolProperty}"...
In your ViewModel you can call your method when the property changes.
public class MyItem
{
//.... other class info
//TODO: Implement INotifyPropertyChanged
private bool _MyBoolProperty = false;
public bool MyBoolProperty
{
get
{
return _MyBoolProperty;
}
set
{
_MyBoolProperty = value;
MyBoolPropertyChanged();
}
}
private void MyBoolPropertyChanged()
{
//do something
}
}
Related
I have a binding to a generic DataTable where some rows may contain problems and should not be modified. There seems to be a very easy way to accomplish that by simple setting IsEnabled in DataGrid_LoadingRow or by a Trigger with Binding in XAML.
However, I also have a “Info”-Column which has a Button in it so that the user can view the problem… Setting IsEnabled to false also disables my button…
I already tried: IsManipulationEnabled but this has no effect.
How can I accomplish this? Is the only way for doing that by traversing the VisualTree of the DataRowView and set IsEnabled for all Cells except the first?
For your first column, use this Button,
public class EnabledButton : Button
{
static EnabledButton()
{
UIElement.IsEnabledProperty.OverrideMetadata(typeof(EnabledButton),
new FrameworkPropertyMetadata(true, FrameworkPropertyMetadataOptions.None,
UIElement.IsEnabledProperty.DefaultMetadata.PropertyChangedCallback,
new CoerceValueCallback(IsEnabledCoerceCallback)));
}
private static object IsEnabledCoerceCallback(DependencyObject d, object baseValue)
{
return (bool)baseValue;
}
}
Usage :
<DataGrid.Columns>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<local:EnabledButton IsEnabled="True" Content="Modify"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
...
</DataGrid.Columns>
This overrides the inheritance of DataGridCell.IsEnabled property.
I have property UserSet which contains from ObservableCollection<GridRow>.
GridRow - my class, which contains 4 properties like this:
public int Id
{
get { return id; }
set
{
id = value;
RaisePropertyChanged("Id");
}
}
I populate UserSet, then Grid binds to it. When I change id field works setter Id. It sets right values.
But, after all changes, when I click other button my UserSet has not modified values. So I can't get updated Grid.
This is my XAML:
<DataGrid ItemsSource="{Binding UsersSet, Mode=TwoWay}" AutoGenerateColumns="True">
</DataGrid>
Please help.
You could try and set the UpdateSourceTrigger:
<DataGrid ItemsSource="{Binding UsersSet,
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}"
AutoGenerateColumns="True">
</DataGrid>
Without knowing the rest of your code it is pretty hard to guess.
This is a very basic question. I have a grid, whose data context is bound to a entity framework service. I simply bound the context to service and I can see the data that is getting bound properly. Now, I want to change couple of coulmns to special controls. Like one column has true or false value and that column I want to display a radio button. One column is date value, I want to display date control. How would one go about doing it?
Thanks.
I'm not exactly sure how to do the Radio Button portion of this, but something like this may get you started:
<ListBox x:Name="LayoutRoot" ItemsSource="{Binding Collection}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Text}"/>
<CheckBox Content="True" IsChecked="{Binding Checked, Mode=TwoWay}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
In this case, you would have a checkbox being bound to the boolean value. I'm not exactly sure what you are using for a date control, but you should be able to place that in the stackpanel also and bind it to the dateproperty of your item.
In the above example, 'Collection' is an observable collection of 'MyObject' which is shown below:
MyObject.cs
public class MyObject
{
public string Text { get; set; }
public bool Checked { get; set; }
public bool InverseChecked { get; set; }
public DateTime Date { get; set; }
}
I also understand that you were using a grid, and I'm showing a ListBox. Not sure if this would work for you, but this is how we've approached it in the past.
Hope this helps!
I have a simple ComboBox in my Silverlight 3 application. I want to populate it from an ObservableCollection. The list holds a class that has a Name(string), and a Selected(bool) property. The combo box has as many items as I have in the list, but I cannot seem to get the list data to appear.
Any help would be appreciated.
<ComboBox x:Name="cmbCategory" Grid.Column="3">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}"/>
<CheckBox IsChecked="{Binding Selected}"/>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
...
private class cmbCategoryClass
{
public string Name { get; set; }
public bool Selected { get; set; }
}
private ObservableCollection<cmbCategoryClass> _categories;
....
cmbCategory.DataContext = _categories;
cmbCategory.ItemsSource = _categories;
I can't tell from your code if this is a Codebehind or a ViewModel. I am guessing that you are actually populating the _categories list in code so that it contains at least one cmbCategoryClass object. Try removing the line that sets the DataContext to _categories as your ItemsSource may be looking for a _categories property on the DataContext Check the Output window in Visual Studio when running in debug mode for clues to data binding failures.
I feel really stupid for asking this but I have been thrashing for over 8 hours. How do I get the Selected Item to show its text in my WPF combo box when selected?
Above is an option dialog that allows users to select and configure the available tournament displays. The problem is the selected combo box item shows the UserControl instead of the Display name.
On Window Loaded:
//_displayer is a private member populated using MEF
//[ImportMany(typeof (IDisplayer))]
//private IEnumerable<IDisplayer> _displayers;
DisplayTypeComboBox.ItemsSource = _displayers;
The ComboBox Xaml:
<ComboBox
Name="DisplayTypeComboBox"
Grid.Column="1"
Grid.ColumnSpan="2"
Grid.Row="1"
IsEditable="False"
SelectionChanged="DisplayTypeComboBox_SelectionChanged">
<ComboBox.ItemTemplate>
<DataTemplate>
<ComboBoxItem Content="{Binding DisplayerName}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
The IDisplayer:
public interface IDisplayer
{
string DisplayDataLocation { get; set; }
string DisplayerName { get; }
string DisplayerDescription { get;}
bool WatcherEnabled { get; }
UserControl View { get; }
string DisplayerImageLeft { get; set; }
string DisplayerImageRight { get; set; }
void Update();
}
I don't even want to think about how many hours I have spent trying to solve what should be a simple problem. Why is it so hard to get your selected text to appear as the selected value? I give up, WPF you have beat me into submission. I changed the control to a list box it takes up more room to display the selectable Items but at least it works.
<ListBox
Name="DisplayTypeComboBox"
Grid.Column="1"
Grid.ColumnSpan="2"
Grid.Row="1"
SelectionChanged="DisplayType_SelectionChanged">
<ListBox.ItemTemplate>
<DataTemplate>
<Label Content="{Binding DisplayerName}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I encountered the same thing. Took me a while too. :(
You should have used the ItemContainerStyle and not ItemTemplate.
Because ComboBox wraps the internal items with a ComboBoxItem - you basically wrapped the ComboBoxItem with another one.
Check what DisplayerName member actually contains. Most likely it contains the UserControl name instead of the Display name.
Try using a TextBlock to bind to the DisplayerName instead of a ComboboxItem. I believe that when you set the itemsource, the combo control will wrap the items inside comboboxitems controls automatically.
Edit: I misunderstood your question. Try setting the SelectionBoxItemTemplate.