How to use trigger event in a button inside a datagrid in silverlight using relaycommand mvvm - silverlight-4.0

How to use trigger event in a button inside a datagrid in silverlight using relaycommand mvvm
Iam unable to get selected values in to some Dto , it means once i selected a row for delete , the selected item property showing NULL .how to solve it pls

You can use trigger event like below in datagrid:
<Button Content="Message" Height="23" HorizontalAlignment="Left" Margin="234,116,0,0" Name="btnMsg" VerticalAlignment="Top" Width="75" >
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<si:CallDataMethod Method="HandleShowMessage"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
You have to add necessary reference for this.
For selecteditem you have to set selected item into datagrid and other thing you have to decalre a property in viewmodel:
In Xaml:
<sdk:DataGrid Height="Auto" AutoGenerateColumns="False" ItemsSource="{Binding Emp}" SelectedItem="{Binding SelectedEMp,Mode=TwoWay}" BorderThickness="1" HorizontalAlignment="Left" Name="dataGrid1" VerticalAlignment="Top" Width="auto">
and in Viewmodel:
private EmpInfo _selectedEMp;
public EmpInfo SelectedEMp
{
get { return _selectedEMp; }
set
{
_selectedEMp = value;
on("SelectedEMp");
}
}
Thanks

Related

UWP Command Binding to Button in ItemsControl

In my Xmal I have
<Button
Command = "{Binding FaultClick}"
/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<ItemsControl ItemsSource="{Binding FaultButtons}"
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button command={"Binding FaultCheck"}>
<Grid>
<TextBlock Text={"Binding FaultButtons.Content"}/}
</Grid>
</Button>
</DataTemplate>
</ItemsControl,ItemTemplate>
<ItemsControl>
and in my ViewModel I have
FaultCheck = new RelayCommand(ClickThisFault,() => true);
in the constructor
Public RelayCommand FaultCheck
{
Get;
Private set;
}
public void ClickThisFault()
{
some actions
}
in the body
What I am trying to achieve is to dynamically build a set of buttons that that the user can click to register faults.
the command binding on the button outside the ItemsControl works fine, I put it there to test the binding.
the itemsource binding on the ItemsControl works as well, my dynamic buttons are created but the Command Binding on the Buttons inside the ItemsControl and the Text Binding on the textBlock dosent work.
Am I missing something with Binding Dynamically created objects ?? or is there a better way to do this??

MasterDetail ListView and editable ContentPresenter: what is wrong?

I'm based on the official Microsoft sample to create a MasterDetail ListView:
MasterDetail ListView UWP sample
I have adapted it to my case, as I want that users can edit directly selected items from the ListView. But I meet a strange comportement:
when I add a new item to the ListView, the changes of the current item, done in the details container, are well saved
but when I select an existing item in the ListView, the changes of the current item, done in the details container, are not saved
Here is a screenshot of my app:
The XAML of my ListView is like this:
<!-- Master : List of Feedbacks -->
<ListView
x:Name="MasterListViewFeedbacks"
Grid.Row="1"
ItemContainerTransitions="{x:Null}"
ItemTemplate="{StaticResource MasterListViewFeedbacksItemTemplate}"
IsItemClickEnabled="True"
ItemsSource="{Binding CarForm.feedback_comments}"
SelectedItem="{Binding SelectedFeedback, Mode=TwoWay}">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</ListView.ItemContainerStyle>
<ListView.FooterTemplate>
<DataTemplate>
<CommandBar Background="White">
<CommandBar.Content>
<StackPanel Orientation="Horizontal">
<AppBarButton Icon="Add" Label="Add Feedback"
Command="{Binding AddItemFeedbacksCommand}" />
<AppBarButton Icon="Delete" Label="Delete Feedback"
Command="{Binding RemoveItemFeedbacksCommand}" />
</StackPanel>
</CommandBar.Content>
</CommandBar>
</DataTemplate>
</ListView.FooterTemplate>
</ListView>
The XAML of the ListView's ItemTemplate is:
<DataTemplate x:Key="MasterListViewFeedbacksItemTemplate" x:DataType="models:Feedback_Comments">
<StackPanel Margin="0,11,0,13"
Orientation="Horizontal">
<TextBlock Text="{x:Bind creator }"
Style="{ThemeResource BaseTextBlockStyle}" />
<TextBlock Text=" - " />
<TextBlock Text="{x:Bind comment_date }"
Margin="12,1,0,0" />
</StackPanel>
</DataTemplate>
The XAML of the Details container is like this:
<!-- Detail : Selected Feedback -->
<ContentPresenter
x:Name="DetailFeedbackContentPresenter"
Grid.Column="1"
Grid.RowSpan="2"
BorderThickness="1,0,0,0"
Padding="24,0"
BorderBrush="{ThemeResource SystemControlForegroundBaseLowBrush}"
Content="{x:Bind MasterListViewFeedbacks.SelectedItem, Mode=OneWay}">
<ContentPresenter.ContentTemplate>
<DataTemplate x:DataType="models:Feedback_Comments">
<StackPanel Visibility="{Binding FeedbacksCnt, Converter={StaticResource CountToVisibilityConverter}}">
<TextBox Text="{Binding creator, Mode=TwoWay}" />
<DatePicker Date="{Binding comment_date, Converter={StaticResource DateTimeToDateTimeOffsetConverter}, Mode=TwoWay}"/>
<TextBox TextWrapping="Wrap" AcceptsReturn="True" IsSpellCheckEnabled="True"
Text="{Binding comment, Mode=TwoWay}" />
</StackPanel>
</DataTemplate>
</ContentPresenter.ContentTemplate>
<ContentPresenter.ContentTransitions>
<!-- Empty by default. See MasterListView_ItemClick -->
<TransitionCollection />
</ContentPresenter.ContentTransitions>
</ContentPresenter>
The "CarForm" is the main object of my ViewModel. Each CarForm contains a List of "Feedback_Comments".
So in my ViewModel, I do this when I add a new comment:
private void AddItemFeedbacks()
{
FeedbacksCnt++;
CarForm.feedback_comments.Add(new Feedback_Comments()
{
sequence = FeedbacksCnt,
creator_id = user_id,
_creator = username,
comment_date = DateTime.Now
});
SelectedFeedback = CarForm.feedback_comments[CarForm.feedback_comments.Count - 1];
}
=> the changes done in the Feedback_Comment that was edited before the add are well preserved
I don't do anything when the user select an existing Feedback_Comment: this is managed by the XAML directly.
=> the changes done in the Feedback_Comment that was edited before to select anoter one are not preserved
=> Would you have any explanation?
The TwoWay binding for the Text property is updated only when the TextBox loses focus. However, when you select a different item in the list, the contents of the TextBox are no longer bound to the original item and so are not updated.
To trigger the update each time the Text contents change, so that the changes are reflected immediately, set the UpdateSourceTrigger set to PropertyChanged:
<TextBox Text="{Binding comment, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
Triggering changes everywhere
To ensure your changes are relflected everywhere including the list, you will need to do two things.
First, your feedback_comments is of type ObservableCollection<Feedback_Comments>. This ensures that the added and removed items are added and removed from the ListView.
Second, the Feedback_Comments class must implement the INotifyPropertyChanged interface. This interface is required to let the user interface know about changes in the data-bound object properties.
Implementing this interface is fairly straightforward and is described for example on MSDN.
The quick solution looks like this:
public class Feedback_Comments : INotifyPropertyChanged
{
// your code
//INotifyPropertyChanged implementation
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged( [ CallerMemberName ]string propertyName = "" )
{
PropertyChanged?.Invoke( this, new PropertyChangedEventArgs( propertyName ) );
}
}
Now from each of your property setters call OnPropertyChanged(); after setting the value:
private string _comment = "";
public string Comment
{
get
{
return _comment;
}
set
{
_comment = value;
OnPropertyChanged();
}
}
Note, that the [CallerMemberName] attribute tells the compiler to replace the parameter by the name of the caller - in this case the name of the property, which is exactly what you need.
Also note, that you can't use simple auto-properties in this case (because you need to call the OnPropertyChanged method.
Bonus
Finally as a small recommendation, I see you are using C++-like naming conventions, which does not fit too well into the C# world. Take a look at the recommended C# naming conventions to improve the code readability :-) .

DataBind to Combobox In SilverLight 4 .0

I am trying to databind to the combobox. Data is coming from a database table which name is tbltest and table has 2 fileds id and name.
When I am trying to bind name to combox it display me tbltest:name in View. I am using domain services and MVVM to bind data.
Below is my code of ViewModel:
public ViewModel()
{
var query = context.GetTblTestsQuery();
var load = context.Load(query);
load.Completed += (s, ea) =>
{
ObsCompanyCollection = new ObservableCollection<tblTest>(context.tblTests);
};
}
private ObservableCollection<tblTest> _ObsCompanyCollection = new ObservableCollection<tblTest>();
public ObservableCollection<tblTest> ObsCompanyCollection
{
get
{
return _ObsCompanyCollection;
}
set
{
if (_ObsCompanyCollection != value)
{
_ObsCompanyCollection = value;
NotifyPropertyChanged("ObsCompanyCollection");
}
}
}
and Below is code of my XAml file:
<UserControl.Resources>
<my:ViewModel x:Key="ViewModel"/>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" Background="White" DataContext="{StaticResource ViewModel}">
<ComboBox Height="23" HorizontalAlignment="Left" Margin="47,128,0,0" Name="comboBox1" VerticalAlignment="Top" Width="120" DisplayMemberPath="{Binding name,Mode=TwoWay}" ItemsSource="{Binding ObsCompanyCollection,Mode=TwoWay}" SelectedItem="{Binding tbldata.SelectCompanyId,Mode=TwoWay}" />
I dont know what is wrong with this code. I want only name to display in my combobox.
Thanks
try this
<ComboBox Height="23" HorizontalAlignment="Left" Margin="47,128,0,0" Name="comboBox1" VerticalAlignment="Top" Width="120" DisplayMemberPath="name" ItemsSource="{Binding ObsCompanyCollection,Mode=OneWay}"

How to call command inside listbox in silverlight4

I am using Listbox and it contains button ,and i want to handle button click event using command.but my command never calls.
is this Correct way??
<pmControls:pmListBox Grid.Row="1" Margin="3" ItemsSource="{Binding Countries}" SelectedItem="{Binding SelectedCountry}" >
<pmControls:pmListBox.ItemTemplate >
<DataTemplate >
<Button Command="{Binding GetAllStatesCommand}" CommandParameter="{Binding}" Margin="3" Width="100" Height="50" Content="{Binding Title}">
</Button>
</DataTemplate>
</pmControls:pmListBox.ItemTemplate>
</pmControls:pmListBox>
The DataContext of one list item is different from the DataContextof the surrounding control. To bind that command to the DataContext of that control you have two options:
Either you provide the control with a name and reference to that:
<pmControls:pmListBox x:Name="myCoolListBox" [...]>
<pmControls:pmListBox.ItemTemplate>
<DataTemplate>
<Button Command="{Binding DataContext.GetAllStatesCommand, ElementName=myCoolListBox}" CommandParameter="{Binding}" [...] />
</DataTemplate>
</pmControls:pmListBox.ItemTemplate>
</pmControls:pmListBox>
Or you create class holding your DataContext...
public class DataContextBinder : DependencyObject
{
public static readonly DependencyProperty ContextProperty = DependencyProperty.Register("Context", typeof(object), typeof(DataContextBinder), new PropertyMetadata(null));
public object Context
{
get { return GetValue(ContextProperty); }
set { SetValue(ContextProperty, value); }
}
}
...and create an instance of that in the resources section of your ListBox:
<pmControls:pmListBox x:Name="myCoolListBox" [...]>
<pmControls:pmListBox.Resources>
<local:DataContextBinder x:Key="dataContextBinder" Context="{Binding}" />
</pmControls:pmListBox.Resources>
<pmControls:pmListBox.ItemTemplate>
<DataTemplate>
<Button Command="{Binding Context.GetAllStatesCommand, Source={StaticResource dataContextBinder}" CommandParameter="{Binding}" [...] />
</DataTemplate>
</pmControls:pmListBox.ItemTemplate>
</pmControls:pmListBox>

Silverlight ComboBox in DataGrid Binding SelectedItem problem

I have a combobox in datagrid.I use Silverlight 4.0 and MVVM.
My code works fine,unless when I removed a record from datagrid and add another one, the SelectedValue binding for combobox in added row doesnt work.
<sdk:DataGrid AutoGenerateColumns="False" ItemsSource="{Binding Items, Mode=TwoWay}" Name="dataGrid2" >
<sdk:DataGrid.Columns>
<sdk:DataGridTemplateColumn Width="50*">
<sdk:DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding Path=Products, Mode=OneWay}"
SelectedValue="{Binding Path=ProductId,Mode=TwoWay}"
DisplayMemberPath="ProductTitle"
SelectedValuePath="ProductId"/>
</DataTemplate>
</sdk:DataGridTemplateColumn.CellEditingTemplate>
</sdk:DataGridTemplateColumn>
</sdk:DataGrid.Columns>
</sdk:DataGrid>
Thanks
Found this piece of code on some site, it helped me in a similar Situation:
public class ComboBoxEx : ComboBox
{
protected override void OnItemsChanged(System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
var bindingExpression = GetBindingExpression(SelectedValueProperty);
base.OnItemsChanged(e);
if (bindingExpression != null)
{
var binding = bindingExpression.ParentBinding;
SetBinding(SelectedValueProperty, bindingExpression.ParentBinding);
}
}
}