I've got a datagrid which is bound to an ObservableCollection of the ViewModel below. The Datagrid will display all values correctly, so the binding seems to be working, but if I change some value the Grid won't call the setter's of my VM. Could somebody tell me why?
Here's my ViewModel:
public class DocumentVm : ViewModelBase
{
private Document document;
public bool IsNew { get; private set; }
public Document Document {
get { return document; }
}
public DocumentVm(Document document)
{
this.document = document;
IsNew = false;
}
public DocumentVm(Document document, bool isNew)
{
this.document = document;
IsNew = isNew;
}
public String Name
{
get { return document.Name; }
set { document.Name = value; RaisePropertyChangedEvent("Name");}
}
public String Path
{
get { return document.Path; }
set { document.Path = value; }
}
public String Metadata
{
get { return document.Metadata; }
set { document.Metadata = value; }
}
public int SpeechId
{
get { return document.SpeechId; }
set { document.SpeechId = value; }
}
}
Here is the XAML Code:
<DataGrid Margin="3" Grid.Row="7" Grid.Column="1" BorderThickness="0"
ItemsSource="{Binding Path=CurrentSpeech.Documents, Mode=TwoWay}"
SelectedItem="{Binding Path=CurrentSpeech.CurrentDocument, Mode=TwoWay}">
<DataGrid.Columns>
<DataGridTemplateColumn Header="Name" Width="SizeToCells">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBox Text="{Binding Name, Mode=TwoWay}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="MetaDaten" Width="SizeToCells">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBox Text="{Binding Metadata, Mode=TwoWay}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Pfad" Width="SizeToCells">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
Thank you all!
UpdateSourceTrigger=PropertyChanged on the Bindings was missing.
Not sure why the setters aren't getting called but if you use dependency properties they actually do get called. I'm far too drunk to investigate why the CLR properties aren't getting set in your project but this works for me.
public partial class MainWindow : Window
{ public ObservableCollection<DocumentVm> Items
{
get { return (ObservableCollection<DocumentVm>)GetValue(ItemsProperty); }
set { SetValue(ItemsProperty, value); }
}
public static readonly DependencyProperty ItemsProperty =
DependencyProperty.Register("Items", typeof(ObservableCollection<DocumentVm>), typeof(MainWindow), new PropertyMetadata(null));
public MainWindow()
{
InitializeComponent();
Items = new ObservableCollection<DocumentVm>();
Items.Add(new DocumentVm() { Name = "Name 1"});
Items.Add(new DocumentVm() { Name = "Name 2"});
}
}
public class DocumentVm : DependencyObject
{
public string Name
{
get { return (string)GetValue(NameProperty); }
set { SetValue(NameProperty, value); }
}
public static readonly DependencyProperty NameProperty =
DependencyProperty.Register("Name", typeof(string), typeof(DocumentVm), new PropertyMetadata(null, new PropertyChangedCallback( (s, e)=>
{
// This will run when the property is set.
})));
}
Related
My Problem, I can't remove list in my listbox from browser, but when i debug in my code data list has removed.
View Model
private List<Customer> _listCustomer = new List<Customer>();
public List<Customers> ListCustomers
{
get { return _listCustomers; }
set { _listCustomers = value; OnPropertyChanged("ListCustomers"); }
}
private ICommand _removeCommand;
public ICommand RemoveCommand
{
get { return _removeCommand ?? (_removeCommand = new RelayCommand(param => ButtonRemoveCustomer(), null)); }
set { OnPropertyChanged("ListCustomers"); }
}
private void ButtonRemoveCustomer()
{
ListCustomers.Remove(this.SelectCustomer);
this.SelectCustomer = null;
}
My View
<Intersoft:UXListBox x:Name="CustData" Width="200" MaxHeight="500" SelectedItem="{Binding SelectCustomer, Mode=TwoWay}"
ItemsSource="{Binding ListCustomers, Mode=TwoWay}" ItemTemplate="{StaticResource DataListTemplate}"
VerticalScrollBarVisibility ="Visible" HorizontalScrollBarVisibility="Visible"/>
<Intersoft:UXButton Content="Remove List" Command="{Binding RemoveCommand, Mode=TwoWay}" Width="100"/>
How to fix my code ??
private void ButtonRemoveCustomer()
{
ListCustomers.Remove(this.SelectCustomer);
OnPropertyChanged("ListCustomers");
this.SelectCustomer=null;
}
I use on the following DataGrid:
<DataGrid SelectedValuePath="Key" DisplayMemberPath="Value" ItemsSource="{Binding MyModelGrid}">
<DataGrid.Columns>
<DataGridTemplateColumn Width="*" Header="{x:Static p:Resources.XHeader}">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox IsEditable="True" SelectedItem="{Binding Value.X}" ItemsSource="{Binding DataContext.XList,RelativeSource={RelativeSource AncestorType=DataGrid,Mode=FindAncestor}}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
//More details...
</DataGrid.Columns>
</DataGrid>
It's DataContext is the following Model:
public class MyModel: INotifyPropertyChanged
{
private SortedDictionary<int, GridRowObj> _myModelGrid= new SortedDictionary<int,GridRowObj>();
public SortedDictionary<int, GridRowObj> MyModelGrid
{
get
{
return _myModelGrid;
}
set
{
if (_myModelGrid!= value)
{
_myModelGrid= value;
OnPropertyChanged("MyModelGrid");
}
}
}
private ObservableCollection<string> _xList;
public ObservableCollection<string> XList
{
get
{
return _xList;
}
set
{
if (_xList!= value)
{
_xList= value;
OnPropertyChanged("XList");
}
}
}
}
The Dictonary - MyModelGrid initialized in 20 rows (they are displayed on the screen).
And when I put data to the list - XList, the PropetyChangedEvent is null, so the list is displayed empty.
I think I'm missing something in the binding. I can not understand why the event is null?
EDIT:
DataContext setting :
public MyView()
{
InitializeComponent();
MyViewModel vm = new MyViewModel();
this.DataContext = vm.Model;
}
MyViewModel.cs:
public class MyViewModel: INotifyPropertyChanged
{
private MyModel _model = new MyModel();
public MyModel Model
{
get
{
return _model;
}
set
{
_model= value;
NotifyPropertyChanged("Model");
}
}
}
I have information that was gathered from a service about TFS builds put into ViewModels.
Here are the models:
public class Collection : ViewModel
{
private string _name = string.Empty;
public string Name
{
get { return _name; }
set
{
_name = value;
OnPropertyChanged(() => Name);
}
}
private ObservableCollection<Project> _projects = new ObservableCollection<TFSProject>();
public ObservableCollection<Project> Projects
{
get { return _projects; }
set
{
_projects = value;
OnPropertyChanged(() => Projects);
}
}
}
public class Project : ViewModel
{
private string _name = string.Empty;
public string Name
{
get { return _name; }
set
{
_name = value;
OnPropertyChanged(() => Name);
}
}
private ObservableCollection<string> _buildDefinitions = new ObservableCollection<string>();
public ObservableCollection<string> BuildDefinitions
{
get { return _buildDefinitions; }
set
{
_buildDefinitions = value;
OnPropertyChanged(() => BuildDefinitions);
}
}
}
I am binding my combobox's itemssource to a ObservableCollection<Collection>. The problem is that the collection, project, and build definition names are stored in a class that defines them as separate string properties:
public class BuildMonitor : INotifyPropertyChanged
{
[Description("In TFS, each team project exists within a TFS Collection. This is the name of the collection applicable to the build that this monitor is for. Default='Vision2010'")]
public string Collection
{
get { return collection_; }
set
{
collection_ = value;
OnPropertyChanged(() => Collection);
}
}
private string collection_ = "Vision2010";
[Description("BuildDefintions reside within a TeamProject. This is the name of the TeamProject where the build definition this monitor is for resides. Default='Double-Take2010'")]
public string TeamProject { get { return teamProject_; } set { teamProject_ = value; OnPropertyChanged(() => TeamProject); } }
private string teamProject_ = "Double-Take2010";
[Description("Builds are defined in TFS as the execution of a particular BuildDefinition. This is the name of the build defintion (thus; the build) this monitor is for.")]
public string BuildDefinition { get { return buildDefinition_; } set { buildDefinition_ = value; OnPropertyChanged(() => BuildDefinition); } }
private string buildDefinition_;
[Description("Used only if this monitor should watch for builds specified by a particular user. Enter the domain name of the user, or leave blank to monitor builds by any user.")]
public string RequestedByFilter { get { return requestedByFilter_; } set { requestedByFilter_ = value; OnPropertyChanged(() => RequestedByFilter); } }
private string requestedByFilter_;
[Description("The command to execute when the build monitor is triggered.")]
public string Command { get { return command_; } set { command_ = value; OnPropertyChanged(() => Command); } }
private string command_;
[Description("The arguments to pass to the command. Arguments will resolve known build monitor macros.")]
public string Arguments { get { return arguments_; } set { arguments_ = value; OnPropertyChanged(() => Arguments); } }
private string arguments_;
[Description("If TRUE, the monitor will fire only once, at which point it will be marked as 'invalid' and never fire again.")]
public bool RunOnce { get { return runOnce_; } set { runOnce_ = value; OnPropertyChanged(() => RunOnce); } }
private bool runOnce_ = false;
[Description("The maximum age (in hours) a build can be (since finished), for the monitor to consider it for processing. Default='0'")]
public int MaxAgeInHours { get { return maxAgeInHours_; } set { maxAgeInHours_ = value; OnPropertyChanged(() => MaxAgeInHours); } }
private int maxAgeInHours_ = 0;
[Description("Which status trigger the monitor should 'fire' on. When the build status matches this trigger, the monitor command will be executed. Default='Succeeded'")]
public BuildStatus EventTrigger { get { return eventTrigger_; } set { eventTrigger_ = value; OnPropertyChanged(() => EventTrigger); } }
private BuildStatus eventTrigger_ = BuildStatus.Succeeded;
[Browsable(false), Description("Used internally to reliably compare two BuildMonitors against each other.")]
public Guid ID { get { return id_; } set { id_ = value; } }
private Guid id_ = Guid.NewGuid();
[Browsable(false), Description("Used internally to determine if the monitor is still valid/should be processed.")]
public bool IsEnabled { get { return isEnabled_; } set { isEnabled_ = value; } }
private bool isEnabled_ = true;
[Browsable(false), XmlIgnore, Description("Used internally to track when the monitor is 'busy' (currently running the 'Command' selected.")]
public int CurrentProcessID { get { return currentProcessID_; } set { currentProcessID_ = value; } }
private int currentProcessID_ = 0;
[Browsable(false), XmlIgnore, Description("Used internally to track the build that the monitor is currently processing.")]
private string currentBuildUri_;
public string CurrentBuildUri { get { return currentBuildUri_; } set { currentBuildUri_ = value; } }
[field: NonSerialized, Browsable(false)]
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged<T>(Expression<Func<T>> propertyExpression)
{
MemberExpression memberExpression = (MemberExpression)propertyExpression.Body;
string propertyName = memberExpression.Member.Name;
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
In my xaml I have attempted to represent the selection of this data by setting the itemssource of the collection combobbox to a relative source binding which is the ObservableCollection<Collection>. I get the items in the list ok but since the itemssource is a List<BuildMonitors>, I can't seem to get the selected item to map over the name property of the selected item to the actual binding of the data item (string Collection in the BuildMonitor instance).
<tk:DataGrid ItemsSource="{Binding Monitors}"
AutoGenerateColumns="False">
<tk:DataGrid.Columns>
<tk:DataGridTemplateColumn Header="Collection">
<tk:DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox x:Name="Collection"
ItemsSource="{Binding Path=AllCollections, RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type apollo:BuildMonitorNew}}}"
DisplayMemberPath="Name"
SelectedItem="{Binding .}"
SelectedValuePath="Collection"
SelectedValue="{Binding Name}"/>
</DataTemplate>
</tk:DataGridTemplateColumn.CellEditingTemplate>
<tk:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Collection,Mode=TwoWay}"/>
</DataTemplate>
</tk:DataGridTemplateColumn.CellTemplate>
</tk:DataGridTemplateColumn>
<tk:DataGridTemplateColumn Header="Project">
<tk:DataGridTemplateColumn.CellEditingTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding ElementName=Collection,Path=SelectedItem.Projects}">
<ComboBox x:Name="Projects"
ItemsSource="{Binding}"
DisplayMemberPath="Name"/>
</HierarchicalDataTemplate>
</tk:DataGridTemplateColumn.CellEditingTemplate>
</tk:DataGridTemplateColumn>
<tk:DataGridTextColumn Binding="{Binding Command}"
Header="Command"/>
<tk:DataGridTextColumn Binding="{Binding Arguments}"
Header="Arguments"
Width="*"/>
</tk:DataGrid.Columns>
My first thought is that although my viewmodel may be a better representation of the data (hierarchical), the structure of the data to select vs the data to actual store is too different.
I would love to be wrong here and find a snazzy way to convert the data that is actually selected(Collection,Project, and then BuildDefinition) to the path of the data that is stored (BuildMonitor).
Any ideas?
I found that the multivalue converter allowed me to transform the hierarchical structure into parts for the combobox item source where they are representing a list.
Converter:
public class BuildMonitorItemSource : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (values.Count() == 2)
{
string collectionToGet = parameter.ToString();
ObservableCollection<TFSCollection> allcollections = values[1] as ObservableCollection<TFSCollection>;
BuildLauncher.BuildMonitor currentBM = (values[0] as BuildLauncher.BuildMonitor);
if (collectionToGet.Equals("Projects"))
{
return allcollections.FirstOrDefault(x => x.Name.Equals(currentBM.Collection, StringComparison.OrdinalIgnoreCase)).Projects;
}
else if (collectionToGet.Equals("BuildDefinitions"))
{
TFSCollection currentCollection = allcollections.FirstOrDefault(x => x.Name.Equals(currentBM.Collection));
TFSProject currentProject = currentCollection.Projects.FirstOrDefault(x => x.Name.Equals(currentBM.TeamProject));
return currentProject.BuildDefinitions;
}
}
return values;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
This is the modified xml:
<tk:DataGrid ItemsSource="{Binding Monitors}"
AutoGenerateColumns="False"
IsEnabled="{Binding RelativeSource={RelativeSource AncestorType=apollo:BuildMonitorNew}, Path=TFSAuthenticated}"
Name="MontiorsGrid">
<tk:DataGrid.Columns>
<tk:DataGridCheckBoxColumn Binding="{Binding IsEnabled}">
<tk:DataGridCheckBoxColumn.Header>
<Ellipse Grid.Column="0"
HorizontalAlignment="Left"
Height="10" Width="10"
Stroke="Black"
StrokeThickness="1"
Fill="Green"/>
</tk:DataGridCheckBoxColumn.Header>
</tk:DataGridCheckBoxColumn>
<tk:DataGridTemplateColumn Header="Collection">
<tk:DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox x:Name="CollectionCombo"
ItemsSource="{Binding Path=AllCollections, RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type apollo:BuildMonitorNew}}}"
DisplayMemberPath="Name"
SelectedValue="{Binding Collection}"
SelectedValuePath="Name">
</ComboBox>
</DataTemplate>
</tk:DataGridTemplateColumn.CellEditingTemplate>
<tk:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Collection,Mode=TwoWay}"/>
</DataTemplate>
</tk:DataGridTemplateColumn.CellTemplate>
</tk:DataGridTemplateColumn>
<tk:DataGridTemplateColumn Header="Project">
<tk:DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox x:Name="Projects"
DisplayMemberPath="Name"
SelectedValue="{Binding TeamProject}"
SelectedValuePath="Name">
<ComboBox.ItemsSource>
<MultiBinding Converter="{StaticResource GetItemSource}" ConverterParameter="Projects" >
<Binding Path="." />
<Binding Path="AllCollections" RelativeSource="{RelativeSource Mode=FindAncestor,AncestorType={x:Type apollo:BuildMonitorNew}}"/>
</MultiBinding>
</ComboBox.ItemsSource>
</ComboBox>
</DataTemplate>
</tk:DataGridTemplateColumn.CellEditingTemplate>
<tk:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding TeamProject,Mode=TwoWay}"/>
</DataTemplate>
</tk:DataGridTemplateColumn.CellTemplate>
</tk:DataGridTemplateColumn>
<tk:DataGridTemplateColumn Header="Build Definition">
<tk:DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox SelectedItem="{Binding BuildDefinition}">
<ComboBox.ItemsSource>
<MultiBinding Converter="{StaticResource GetItemSource}" ConverterParameter="BuildDefinitions">
<Binding Path="." />
<Binding Path="AllCollections" RelativeSource="{RelativeSource Mode=FindAncestor,AncestorType={x:Type apollo:BuildMonitorNew}}"/>
</MultiBinding>
</ComboBox.ItemsSource>
</ComboBox>
</DataTemplate>
</tk:DataGridTemplateColumn.CellEditingTemplate>
<tk:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding BuildDefinition,Mode=TwoWay}"/>
</DataTemplate>
</tk:DataGridTemplateColumn.CellTemplate>
</tk:DataGridTemplateColumn>
<tk:DataGridTextColumn Binding="{Binding Command}"
Header="Command"/>
<tk:DataGridTextColumn Binding="{Binding Arguments}"
Header="Arguments"
Width="*"/>
</tk:DataGrid.Columns>
</tk:DataGrid>
I have a UserControl with ComboBox.
<ComboBox Grid.Row="8" Grid.Column="1"
VerticalAlignment="Center"
x:Name="cmbCategory"
ItemsSource="{Binding ElementName=ucAppiGeneralInfo, Path=Categories, Mode=TwoWay}"
SelectedItem="{Binding ElementName=ucAppiGeneralInfo, Path=SelectedCategory, Mode=TwoWay}"
IsEditable="True"
IsSynchronizedWithCurrentItem="True"
SelectedValuePath="CAT_ID"
TextSearch.TextPath="CAT_NAME">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=CAT_NAME}"/>
<TextBlock Text=" - "/>
<TextBlock Text="{Binding Path=PUBLIC_DESCRIPTION}"/>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
The code behind is:
public partial class AppiGeneralInfoUC : UserControl
{
public DataTable Categories
{
get { return (DataTable)GetValue(CategoriesProperty); }
set { SetValue(CategoriesProperty, value);}
}
public static readonly DependencyProperty CategoriesProperty =
DependencyProperty.Register(
"Categories",
typeof(DataTable),
typeof(AppiGeneralInfoUC),
new UIPropertyMetadata(null));
public String SelectedCategory
{
get { return (String)GetValue(SelectedCategoryProperty); }
set
{
SetValue(SelectedCategoryProperty, value);
}
}
public static readonly DependencyProperty SelectedCategoryProperty =
DependencyProperty.Register(
"SelectedCategory",
typeof(String),
typeof(AppiGeneralInfoUC),
new UIPropertyMetadata(null));
public AppiGeneralInfoUC()
{
InitializeComponent();
}
}
I have a window which use the UserControl:
<TabControl>
<TabItem Header="Information">
<my:AppiGeneralInfoUC x:Name="ucAppiGeneralInfo"
Categories="{Binding Path=Categories, Mode=TwoWay}"
SelectedCategory="{Binding Path=SelectedCategory, Mode=TwoWay}" />
</TabItem>
the code behind is:
public partial class ApplicationWindow : Window
{
VMBase appiGeneralInfoWin = new AppiGeneralInfoVM();
public ApplicationWindow()
{
InitializeComponent();
ucAppiGeneralInfo.DataContext = appiGeneralInfoWin;
}
public void updateAction(string cat_id)
{
this.Title = "Update application";
(appiGeneralInfoWin as AppiGeneralInfoVM).setSelectedCategory(cat_id);
} ...
And finally I have ViewModel class:
class AppiGeneralInfoVM : VMBase
{
private DataTable categories = null;
private String selectedCategory = null;
public DataTable Categories
{
get { return this.categories; }
set
{
this.categories = value;
this.OnPropertyChanged("Categories");
}
}
public String SelectedCategory
{
get { return this.selectedCategory; }
set
{
this.selectedCategory = value;
this.OnPropertyChanged("SelectedCategory");
}
}
public AppiGeneralInfoVM()
{
ServicesLoader.LoadRunTimeServices();
Categories = GetService<CategoryBLL>().getCategories();
}
public void setSelectedCategory(string cat_id)
{
SelectedCategory = Categories.Select("cat_id =" + "'"+cat_id+"'")[0]["CAT_NAME"].ToString();
}
Everything works well but i have problem with the selectedItem (SelectedCategory),
it's not update at all....
I think it happens because your SelectedItem has string type while your collection is DataTable (which enumerates DataRow). Try changing your collection to be IEnumerable<string>
I just can't make the following situation work:
I have a class, with the following implementation:
public class SelectionItem<T> : ViewModelBase where T : Entity
{
private bool? _isSelected;
public bool? IsSelected
{
get { return _isSelected; }
set
{
_isSelected = value;
RaisePropertyChanged("IsSelected");
}
}
public T Item { get; set; }
}
And I have the following property on my ViewModel:
private IEnumerable<SelectionItem<DB_Aux_Pessoas>> _vendedores;
public IEnumerable<SelectionItem<DB_Aux_Pessoas>> Vendedores
{
get
{
return _vendedores;
}
set
{
_vendedores = value;
RaisePropertyChanged("Vendedores");
}
}
Then, in my View, I have the ComboBox:
<ComboBox Margin="3,0,0,0"
Height="23"
Width="200"
ItemsSource="{Binding Vendedores, Mode=TwoWay}"
Grid.Column="1"
Grid.Row="1"
HorizontalAlignment="Left">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox IsChecked="{Binding IsSelected, Mode=TwoWay}" />
<TextBlock Text="{Binding Item.NomeRazaoSocial}" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
But when I change the CheckBox on the ComboBoxItem, it does not reflect on the property.
The code for DB_Aux_Pessoas is below:
[MetadataTypeAttribute(typeof(DB_Aux_Pessoas.DB_Aux_PessoasMetadata))]
public partial class DB_Aux_Pessoas
{
// This class allows you to attach custom attributes to properties
// of the DB_Aux_Pessoas class.
//
// For example, the following marks the Xyz property as a
// required property and specifies the format for valid values:
// [Required]
// [RegularExpression("[A-Z][A-Za-z0-9]*")]
// [StringLength(32)]
// public string Xyz { get; set; }
internal sealed class DB_Aux_PessoasMetadata
{
// Metadata classes are not meant to be instantiated.
private DB_Aux_PessoasMetadata()
{
}
public Nullable<short> Cliente { get; set; }
public string Id_Numero { get; set; }
public string NomeRazaoSocial { get; set; }
public Nullable<short> Supervisor { get; set; }
public Nullable<short> Vendedor { get; set; }
}
}
What I am doing wrong here?
Tks in advance.
I can't check this right now, but I'm fairly sure the dependency property IsChecked will only accept a binding to a bool and NOT a Nullable<bool>. You might have to do the conversion in your viewmodel and decide which should be the appropriate default for a null value.
This works fine for me. Add an extra property to give you some visual feedback like this:
public class SelectionItem<T> : ViewModelBase
{
private bool? _isSelected;
public bool? IsSelected
{
get { return _isSelected; }
set
{
_isSelected = value;
RaisePropertyChanged("IsSelected");
RaisePropertyChanged("Feedback");
}
}
public string Feedback
{
get
{
if (!this.IsSelected.HasValue)
{
return "null";
}
if (this.IsSelected.Value)
{
return "yes";
}
return "no";
}
}
public T Item { get; set; }
}
And in your xaml, add an extra TextBlock to show the result:
<ComboBox Grid.Column="1"
Grid.Row="1"
Height="23"
Margin="3,0,0,0"
Width="200"
HorizontalAlignment="Left"
ItemsSource="{Binding Vendedores, Mode=TwoWay}">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox IsChecked="{Binding IsSelected, Mode=TwoWay}" />
<TextBlock Text="{Binding Item.NomeRazaoSocial}" />
<TextBlock Text="{Binding Feedback}" Margin="5,0,0,0" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
If you see "Yes", "No", "Null" changing as you click the checkboxes, then it's working. Your code worked for me.
public static readonly DependencyProperty IsCheckedProperty = DependencyProperty.RegisterAttached("IsChecked", typeof(bool), typeof(...),
new PropertyMetadata(false, delegate(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
...
}
IsChecked is bool. You can possibly track BindingExpression Error in Output window.