I'm binding an editable (you can type in it to add items to the list of choices) radcombobox in a column of a radgridview. It is not throwing a binding error, but it is not updating the bound property (Model.Remarks)
Here are the classes
public class NotamRemarkList : List<string>
{
public NotamRemarkList()
{
Add("Precision approaches are down; higher weather minimums apply.");
Add("Due to runway closure, approaches available have higher minimums.");
Add("All approaches are down; weather must be VFR.");
Add("Long runway is closed; issue if the other runways are wet.");
Add("Runway shortened; issue if wet.");
Add("Airport will be closed at the time we are scheduled in.");
Add("Runway lights are inoperative; night flights prohibited.");
}
}
public class NotamViewModel
{
[DataMember]
public string NewStatus { get; set; }
[DataMember]
public Notam Model { get; set; }
[DataMember]
public string NotamGroup { get; set; }
[DataMember]
public int NotamCount { get; set; }
[DataMember]
public DateTime? EarliestNotamDepartureTime { get; set; } // min_dep_datetime
[DataMember]
public string RadioButtonGroupName { get; set; }
}
public class Notam
{
[DataMember]
public string Remarks { get; set; }
[DataMember]
public string TripNumber { get; set; }
[DataMember]
public string ArrivalDeparture { get; set; }
}
Here's the xaml I have tried for the column - the first one uses a cell template, the second attempts to do everything in a column
<telerik:GridViewDataColumn Header="Remarks" IsFilterable="False" IsSortable="False" IsReadOnly="False" Width="430">
<telerik:GridViewDataColumn.CellTemplate>
<DataTemplate>
<telerik:RadComboBox SelectedValue="{Binding Model.Remarks, Mode=TwoWay}" ItemsSource="{StaticResource NotamRemarkList}" IsEditable="True"/>
</DataTemplate>
</telerik:GridViewDataColumn.CellTemplate>
</telerik:GridViewDataColumn>
<telerik:GridViewComboBoxColumn SelectedValueMemberPath="Model.Remarks" UniqueName="colRemarks" IsComboBoxEditable="true" IsFilterable="False" IsSortable="False"/>
public class Notam:INotifyPropertyChanged
{
private string _remarks;
[DataMember]
public string Remarks
{
get {return _remarks;}
set{
_remarks=value ;
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("Remarks"));
}
}
[DataMember]
public string TripNumber { get; set; }
[DataMember]
public string ArrivalDeparture { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
}
<telerik:RadComboBox SelectedValue="{Binding Model.Remarks, Mode=TwoWay}" SelectedValueMemberPath="Model.Remarks" ItemsSource="{StaticResource NotamRemarkList}" IsEditable="True"/>
I hope this will help.
Related
I have two related entities:
public class Event
{
public string ID { get; set; }
public DateTime EventDate { get; set; }
public string EventData { get; set; }
public string DocID1 { get; set; }
public int DocID2 { get; set; }
public virtual Document Document1 { get; set; }
public virtual Document Document2 { get; set; }
}
public class Document
{
public string ID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Number { get; set; }
}
Also created List to display data in WPF:
private ObservableCollection<Event> eventList;
public ObservableCollection<Event> EventList
{
get { return eventList; }
set
{
if (value != eventList)
{
eventList = value;
}
RaisePropertyChanged(nameof(EventList));
}
}
data for my EventList is taken from entity Event:
var query = DBContext.Events.Select(x => x).AsQueryable();
EventList = query.ToList();
What I need is how to set GridControl Column "colFirstName" value to be equal "Document1.FirstName" if DocID1 is not null and "Document2.FirstName" if DocID2 is not null. My XAML code for GridControl is below, could You help how to do it in Xaml, not in ViewModel, or if there is no way to do it in Xaml, what is the best way to do it in ViewModel.
<dxg:GridControl AutoPopulateColumns="False"
ItemsSource="{Binding EventList, UpdateSourceTrigger=PropertyChanged}">
<dxg:GridControl.Columns>
<dxg:GridColumn
x:Name="colEventData"
Width="120"
FieldName="EventData"
Header =" Event data"
Visible="True" >
</dxg:GridColumn>
<dxg:GridColumn
x:Name="colFirsnName"
Width="120"
FieldName="Document1.FirstName"
Header="First Name"
Visible="True"
VisibleIndex="1" />
</dxg:GridControl.Columns>
</dxg:GridControl>
You can use the UnboundExpression property to create a column with a custom expression. For example, to conditionally show values from different properties, use the Iif function:
<dxg:GridColumn FieldName="CustomColumn" x:Name="colFirsnName"
UnboundExpression="Iif(IsNullOrEmpty([DocID1]), [Document2.FirstName], [Document1.FirstName])"
UnboundType="String"/>
This kind of logic should be implemented in the model or view model class. Remember that XAML is only a markup language.
Just create another property that returns the first match and bind to this one. If your entity classes are auto-generated, you could create a new partial class:
public partial class Event
{
public string DocName
{
get
{
if (Document1 != null)
return Document1.FirstName;
if (Document2 != null)
return Document1.LastName;
return null;
}
}
}
<dxg:GridColumn
x:Name="colFirsnName"
Width="120"
FieldName="DocName"
Header="First Name"
Visible="True"
VisibleIndex="1" IsReadOnly="true" />
Hey I have a question about getting an ContactTypeId from the ContactType. This is the object that has an id:
public class ContactType
{
public int ContactTypeId { get; set; }
public string ContactTypeValue { get; set; }
public int ContactId { get; set; }
public DateTime? Added { get; set; }
public DateTime? Updated { get; set; }
public DateTime? Deleted { get; set; }
}
I wrote a WPF application that has a listbox.
<ComboBox x:Name="ContactTypeComboBox" HorizontalAlignment="Left" Margin="110,68,0,0" VerticalAlignment="Top" Width="120" ItemsSource="{Binding ContactTypes}" DisplayMemberPath="ContactTypeValue" SelectedValuePath="ContactTypeId" />
If i get Selected value path doesn't give an ContactTypeId from that object. It only gives a string "ContactTypeId"
Please help me to get a ContactTypeId from ContactType
SelectedValuePath tells the control how to drill down into the selected item and extract a value. The value for the selected item (in this case, its ContactTypeId) is exposed as SelectedValue. That's the property you want to read.
I have datagrid with two columns: text and combobox. And combobox should have binding to observable collection.
This is pseudocode for datagrid items source:
public class ModeObjectState
{
public int ID { get; set; }
public int ObjectTypeID { get; set; }
public string State { get; set; }
}
public class ModeObject
{
public string Name { get; set; }
public int objID { get; set; }
public int Type { get; set; }
public int StateID { get; set; }
public bool Format { get; set; }
}
public class _dataContext
{
public ObservableCollection<ModeObjectState> ListObjectState { get; set; }
public ModeObject ModeObj { get; set; }
}
ObservableCollection<_dataContext> SourceObjList
objTable.ItemsSource = SourceObjList;
This is xaml code for datagrid:
<DataGrid x:Name="objTable" AutoGenerateColumns="False" >
<DataGrid.Columns>
<DataGridTextColumn x:Name="ColumnName" Binding="{Binding Path=ModeObj.Name}" IsReadOnly="True" />
<DataGridComboBoxColumn x:Name="ColumnState" ItemsSource="{Binding ListObjectState}" DisplayMemberPath="State" SelectedValuePath="ID" SelectedValueBinding="{Binding Path=ModeObj.StateID}" />
</DataGrid.Columns>
</DataGrid>
But datagrid doesn't show any items in comboboxcolumn. Please, help me with binding the datagridcombobox to observable collection "ListObjectState" in "_dataContext" class.
Thanks!
Implement with INotifyPropertyChanged for the _dataContext
public class _dataContext : INotifyPropertyChanged
{
private ObservableCollection<ModeObjectState> _listObjectState;
public ObservableCollection<ModeObjectState> ListObjectState
{
get { return _listObjectState; }
set
{
_listObjectState = value;
OnPropertyChagned("ListObjectState");
}
}
public ModeObject ModeObj { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChagned(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
Since the 1st set may done after the Binding, so it wont affect the UI..
Its difficult to figure out without looking at the whole code. You have binding issue, and it would be easier to find where the issue is using XAML debugging tools like Snoop or WPF Inspector. You just need to attach your running application to see the Datacontext.
You can easily find if the datacontext is valid or not.
WPF Inspector has a better User interface, but its prone to crash. Press Ctrl+Shift and hover mouse over your control to see it getting reflected in Snoop/WPF Inspected.
Also see your Output window for whats the binding error you are getting.
I've been sitting on this problem for hours now,
I've got this partial xaml code:
<TextBlock Text="{Binding temprature}" Height="30" HorizontalAlignment="Left" Margin="13,119,0,0" Name="textBlock1" VerticalAlignment="Top" Width="68" />
<TextBlock Height="30" HorizontalAlignment="Left" Name="commentsTextBlock" Text="Comments:" VerticalAlignment="Bottom" Margin="12,0,0,-31" />
<ListBox Margin="2,785,-14,-33" ItemsSource="{Binding comments}" DataContext="{Binding}" Name="commentsListBox">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Margin="0,0,0,17">
<StackPanel Width="311">
<TextBlock Text="{Binding poster_username}" TextWrapping="NoWrap" Style="{StaticResource PhoneTextSubtleStyle}" TextTrimming="WordEllipsis" Width="Auto" Foreground="White" FontFamily="Segoe WP Semibold" />
<TextBlock Text="{Binding comment_text}" TextWrapping="Wrap" Margin="12,-6,12,0" Style="{StaticResource PhoneTextSubtleStyle}" TextTrimming="WordEllipsis" MaxHeight="100" />
</StackPanel>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
And I have this class (Thread) which include a List of comments that should be displayed in the ListBox.
public class Thread : INotifyPropertyChanged
{
public string title { get; set; }
public string deal_link { get; set; }
public string mobile_deal_link { get; set; }
public string deal_image { get; set; }
public string deal_image_highres { get; set; }
public string description { get; set; }
public string submit_time { get; set; }
public bool hot_date { get; set; }
public string poster_name { get; set; }
public double temperature { get; set; }
public double price { get; set; }
public int timestamp { get; set; }
public string expired { get; set; }
public Forum forum { get; set; }
public Category category { get; set; }
public object merchant { get; set; }
public object tags { get; set; }
public int thread_id { get; set; }
public string visit_link { get; set; }
public string hot_time { get; set; }
public int comment_count { get; set; }
public string availability { get; set; }
public string can_vote { get; set; }
public string seen { get; set; }
public List<Comment> comments { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
public void Convert2Unicode()
{
UnicodeEncoding unicode = new UnicodeEncoding();
Byte[] encodedBytes = unicode.GetBytes(title);
title = String.Format("[{0}]", title);
}
private void NotifyPropertyChanged(String propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (null != handler)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
public void SetComments(string content)
{
PaginatedComments commentsList;
this.comments.Clear();
DataContractJsonSerializer serializer =
new DataContractJsonSerializer(typeof(PaginatedComments));
using (MemoryStream ms = new MemoryStream(Encoding.Unicode.GetBytes(content)))
{
commentsList = (PaginatedComments)serializer.ReadObject(ms);
}
foreach (var thread in commentsList.data.comments)
{
this.comments.Add(thread);
}
}
public Thread()
{
comments = new List<Comment>();
}
public void addComments()
{
List<string> parameters = new List<string>();
parameters.Add("thread_id=" + thread_id);
parameters.Add("results_per_page=10");
parameters.Add("page=1");
// Set the data context of the listbox control to the sample data
APICalls.makeRequest(APICalls.ViewingPaginatedComments, parameters, SetComments);
}
//
// Sets the "Seen" variable depending if the item is new (since the last time the application was opened
//
public void updateNewItems()
{
try
{
int last_seen = (int)IsolatedStorageSettings.ApplicationSettings["lastrun"];
if (last_seen < timestamp)
{
seen = "New";
}
else
{
seen = "";
}
}
catch (System.Exception e)
{
IsolatedStorageSettings.ApplicationSettings["lastrun"] = APICalls.GetIntTimestamp();
IsolatedStorageSettings.ApplicationSettings.Save();
MessageBox.Show(e.Message);
}
IsolatedStorageSettings.ApplicationSettings["lastrun"] = APICalls.GetIntTimestamp();
IsolatedStorageSettings.ApplicationSettings.Save();
}
}
public class Comment
{
public string poster_username { get; set; }
public string post_date { get; set; }
public string comment_text { get; set; }
public int timestamp { get; set; }
public int like_count { get; set; }
public string comment_edit_text { get; set; }
}
public class CommentData
{
public List<Comment> comments { get; set; }
public int comment_count { get; set; }
public int total_comments { get; set; }
}
public class PaginatedComments
{
public string response_status { get; set; }
public CommentData data { get; set; }
}
If I load the comments into the Thread before changing the DataCotext to this specific thread. the comments are shown, but when I update the comments after changing the DataContext and navigating to the page the comments are not shown (I have other fields in the rest of the xaml page that are binded to the same instance and they work perfectly. only the comments don't work!
I really appreciate your help!
Thanks
You should be using
public ObservableCollection<Comment> comments{ get; set;}
instead of
public List<Comment> comments { get; set; }
The ObservableCollection sends update notices to the view anytime one of the items(in this case a Comment ) is added or removed.
Note: It won't update the Comment . To have the items bound to the Comment update, Comment has to implement INotifyPropertyChanged.
Your property is a simple List<T>. Silverlight needs to be signaled when something changes, using events.
A List<T> does not raise any event when items are being added/removed, so Silverlight cannot detect the new items and thus does not update the UI. The simplest way to make this work is usually to use an ObservableCollection<T> instead of a list.
This collection will raise events that Silverlight knows to listen to.
Please note that for this to work you should not call Add/Remove/Clear from any other thread than the U/I (Dispatcher) thread, since Silverlight controls are not thread-safe (and the events are raised on the thread that performs the Add/Remove/Clear call). To do that, simply make sure you call Dispatcher.BeginInvoke from your SetComments method (since it seems to be a callback happening from whatever your fetching mechanism is).
Alternatively, you could also regenerate a brand new List object when fetching comments, and raise the NotifyPropertyCHanged event in the SetComments method, but that would lead to losing the current selection and resetting your list to the top, which is probably not what you want to do.
My page's data context is set to an Instance of a Project class and all of the other fields in the page are working properly. Each project has another class associated with it as a property. This represents data from another company that we are integrating into this page.
I am attempting to bind to this sub object's TypeID property. Here is a sketch of the objects.
public class Project
{
public int Id { get; set; }
public string ProjectName { get; set; }
public ABCProject ABCProject { get; set; }
}
public class ABCProject
{
public int Id { get; set; }
public int ABCProjectTypeId { get; set; }
public ABCProjectType { get; set; }
}
public class ABCProjectType
{
public int ProjectTypeId { get; set; }
public string TypeName { get; set; }
}
Here is what my XAML looks like:
<telerik:RadComboBox Grid.Column="2" Grid.Row="1" telerik:StyleManager.Theme="Metro" x:Name="ProjectTypeCombo"
ItemsSource="{Binding ProjectTypePickList}"
SelectedValue="{Binding ABCProject.ABCProjectTypeId, Mode=TwoWay}"
SelectedValuePath="ABCProjectTypeId"
DisplayMemberPath="TypeName"/>
The pick list is being bound properly. The issue is that the selected value and selected value path don't seem to be binding as I get a blank combobox when the page loads.