|
I have also now tried using interactivity on the TextBox on the FocusLost, but get the following error. I have a command LostFocusCommand in my ViewModel, but it expects to see it on Object "XmlAttribute". How Can I do this as this is somewhere within the Document of the XmlDataProvider I assume?
<TextBox x:Name="value" Text="" FontSize="14" >
<i:Interaction.Triggers>
<i:EventTrigger EventName="LostFocus">
<i:InvokeCommandAction Command="{Binding LostFocusCommand, Mode=OneWay}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBox>
System.Windows.Data Error: 40 : BindingExpression path error: 'LostFocusCommand' property not found on 'object' ''XmlAttribute' (HashCode=38729837)'. BindingExpression:Path=LostFocusCommand; DataItem='XmlAttribute' (HashCode=38729837); target element is 'InvokeCommandAction' (HashCode=20475002); target property is 'Command' (type 'ICommand')
|
|
|
|
|
Let's say I want to subscribe to the Page.Loaded or Page.Initialized event, but I don't want the event handler in my code-behind implementation of the derived Page class, I want it wired up to either a static handler in some other class or a handler in an instance of another class.
How do I do that? I've been searching and searching, and no luck.
Marc
|
|
|
|
|
What you need to do is wire up an EventToCommand to a command in the ViewModel.
|
|
|
|
|
Pete O'Hanlon wrote: What you need to do is wire up an EventToCommand to a command in the ViewModel.
Thanks Pete. I looked up EventToCommand -- so, if I understand this correctly, it's not part of WPF but something that someone else wrote? And if I understand this also correctly, I can't just tell the WPF parser/BAML "here's some instances of things you should know about because I want to wire up events to handlers in those instances?" Or, even if I instantiate those other things, I can't bind events to handlers in those other instances?
Ummm...If all that is true, I would have to say, I'm really disappointed with XAML.
Marc
|
|
|
|
|
Marc Clifton wrote: if I understand this correctly, it's not part of WPF but something that someone else wrote? Correct.Marc Clifton wrote: f I understand this also correctly, I can't just tell the WPF parser/BAML "here's some instances of things you should know about because I want to wire up events to handlers in those instances?" Or, even if I instantiate those other things, I can't bind events to handlers in those other instances? Again, correct - well correct(ish). As I don't really know what you're trying to accomplish here, I can't offer any concrete advice other than to say that your page may be made up of multiple user controls - each with their own DataContext, and the events would be coming via that route. Of course, the way I would tend to handle something like what I think you are trying to accomplish would be to inject the class that you have that's currently static as a dependency and expose it as a property that way. Now my view can bind directly to it - it's clean and easy to test.
|
|
|
|
|
What Pete says - but out of interest, why not put it in the code behind?
MVVM # - I did it My Way
___________________________________________
Man, you're a god. - walterhevedeich 26/05/2011
.\\axxx
(That's an 'M')
|
|
|
|
|
You know precisely why not, your'e just stirring the pot. "the purist" approach it to have no code behind.
Never underestimate the power of human stupidity
RAH
|
|
|
|
|
No I don't, no I"m not.
What is this 'purist' approach of which you speak?
My understanding of the pattern is that the GUI stuff is separated from the ViewModel stuff. MVVM != WPF and in WPF both CAML and .cs code behind are used together to build a class. It is that class's responsibility to provide the UI to implement the ViewModel, as it were.
Nowhere in the MVVM pattern does it prescribe anything to do with code behind.
So some folk have taken it upon themselves to say 'thou shalt not have code behind' because (I think) if they don't , some careless programmers will start putting business logic in the code behind - which is bad, not because it is in the code behind but because it is in the UI class which should not be implementing business logic.
But I don't understand why people feel the need to write additional Xaml functionality - often quite complex and usually a variation on some theme functionality - to avoid using two or three lines of code in the code behind.
I believe it is wrong, as having UI functionality in C# in code behind is often more 'obvious' to the maintenance programmer, and frequently less complex.
MVVM # - I did it My Way
___________________________________________
Man, you're a god. - walterhevedeich 26/05/2011
.\\axxx
(That's an 'M')
|
|
|
|
|
_Maxxx_ wrote: but out of interest, why not put it in the code behind?
1. It seems ridiculous to put the event wire-up in the code-behind when in my opinion, I would think XAML should be able to handle the wire-up declaratively.
2. I don't want the functionality in the Page's code-behind because I have functionality that is common to all pages but needs to be wired up to each button on the page.
3. It's ridiculous to me to write a code-behind handler in each page for each button that then calls some common code elsewhere -- why can't I just wire up the event in the XAML?
4. Clearly I can wire-up the event in the code-behind, why would I be restricted from doing exactly the same thing declaratively in the XAML?
So far, doing this one simple thing, it appears I have stumbled across a serious XAML inadequacy. Is that correct?
(And please, don't go on about MVVM and all that rot -- there are many scenarios where MVVM is not the right approach, and I happen to be dealing with one of them.)
Marc
|
|
|
|
|
Marc Clifton wrote: 1. It seems ridiculous to put the event wire-up in the code-behind when in my opinion, I would think XAML should be able to handle the wire-up declaratively.
I agree - it should, but it doesn't in many cases. So many folk write their own event-to-command handlers and the like to add that functionality. I personally don't like the approach of having heavy framework code to support something that should be simple out-of-the-box.
Marc Clifton wrote: 2. I don't want the functionality in the Page's code-behind because I have functionality that is common to all pages but needs to be wired up to each button on the page.
Buttons are different - buttons support commands so you can bind a button to a command, no problems, in your Xaml
Marc Clifton wrote: 3. It's ridiculous to me to write a code-behind handler in each page for each button that then calls some common code elsewhere -- why can't I just wire up the event in the XAML?
As mentioned, for Buttons you can, but not for all events. So 9for example) a double-click on some gui element will need 'something' in addition to out-of-the-box xaml.
Marc Clifton wrote: 4. Clearly I can wire-up the event in the code-behind, why would I be restricted from doing exactly the same thing declaratively in the XAML?
Because the developers in MS didn't implement the functionality - I don't know of any underlying problem that would stop you being able to do this - after all, there are lots of 'tricks' ot there to effectively give you this functionality.
Marc Clifton wrote: So far, doing this one simple thing, it appears I have stumbled across a serious XAML inadequacy. Is that correct?
IMHO yes.
Marc Clifton wrote: (And please, don't go on about MVVM and all that rot -- there are many scenarios where MVVM is not the right approach, and I happen to be dealing with one of them.)
I wouldn't dream of it Regardless as to whether you are using MVVM or spaghetti-hoop code, it would seem remarkably sensible for XAML to support event-to-DataContextMethod out of the box.
Incidentally (& I'm thinking out loud) you could have a base View class possibly, with the event handler in there which your many XAML views could use? (i'd have a play myself, but I'm not in front of my Windows dev environment right now.
MVVM # - I did it My Way
___________________________________________
Man, you're a god. - walterhevedeich 26/05/2011
.\\axxx
(That's an 'M')
|
|
|
|
|
I've been reading that this can't be done.
Here's an example:
<Page.CommandBindings>
<local:StateCommandBinding
Command="{x:Static local:Pages.ChooseLanguage.CustomRoutedCommand}"
Executed="{x:Static local:Commands.ExecutedCommandEnglish}"
CanExecute="CanExecute"
State="SwipeCardToBegin" />
</Page.CommandBindings>
Where StateCommandBinding is derived from CommandBinding . This works fine if ExecutedCommandEnglish is defined in the Page , but here I'm trying to wire it up in its own "controller" class, if you will, a static class with a static public method.
Ideas?
Marc
|
|
|
|
|
I have a dataset and I want to bind my richtextbox to a field so that it autopopulates and when user leaves the textbox it validates for changes and updates the database field. How do I do this in WPF?
In winforms it is simple as rtb.Databindings.Add("Text", datasource, datafield)
but this is not in WPF
|
|
|
|
|
You have posted this in the C# forum - and you were pointed in the right direction. No one is going to do the work for you. Go through the answers in the link you were given and test some of them out. And don't cross post questions.
When I was a coder, we worked on algorithms. Today, we memorize APIs for countless libraries — those libraries have the algorithms - Eric Allman
|
|
|
|
|
Hi,
I'm trying to handle the RowEditEnding Event on my dataGrid that contains data from LINQ to SQL context. Datagrid contains following items:
<DataGrid RowEditEnding="dtgMyList_RowEditEnding" ItemsSource="{Binding ListAllItems}" AutoGenerateColumns="False" Grid.Row="1" x:Name="dtgMyList" Margin="2,2,2,2" VerticalAlignment="Top">
<DataGrid.Columns>
<DataGridTextColumn IsReadOnly="True" Binding="{Binding ArtikelID, NotifyOnSourceUpdated=True}" Header="ID"/>
<DataGridTextColumn IsReadOnly="False" Binding="{Binding ArtikelBeschreibung, UpdateSourceTrigger=LostFocus}" Header="Beschreibung"/>
<DataGridTextColumn IsReadOnly="False" Binding="{Binding Gesperrt,UpdateSourceTrigger=LostFocus}" Header="Gesperrt"/>
</DataGrid.Columns>
</DataGrid>
So far I'm able to implement the Event handling in code behind, but this is against MVVM Guidelines.
Current implementation:
In View
public delegate void RowEditIntercept(object sender, DataGridRowEditEndingEventArgs e);
public event RowEditIntercept MyRowChanged;
private void dtgMyList_RowEditEnding(object sender, DataGridRowEditEndingEventArgs e)
{
MyDataDataSerice ser = new MyDataDataSerice(this);
MyRowChanged(sender, e);
}
In MyDataService class
private MainWindow _window;
public MyDataDataSerice(MainWindow window)
{
_window = window;
this._window.MyRowChanged += new RowEditIntercept(DoEditMyRows);
}
internal void DoEditMyRows(object sender, DataGridRowEditEndingEventArgs e)
{
if (e.EditAction == DataGridEditAction.Commit)
{
linqMyDataDataContext context = new linqMyDataDataContext();
tblStammDaten stamm = e.Row.DataContext as tblStammDaten;
var matchedData = (from em in context.GetTable<tblStammDaten>()
where em.ArtikelID == stamm.ArtikelID
select em).SingleOrDefault();
matchedData.ArtikelBeschreibung = stamm.ArtikelBeschreibung;
matchedData.Gesperrt = stamm.Gesperrt;
context.SubmitChanges();
}
}
If I understand correctly, I need to find a way to intercept the Event arguments (object sender, DataGridRowEditEndingEventArgs e).
How can I do this in my ViewModel withough writing code in the View?
Thanks in advance!
Piotr
|
|
|
|
|
The easiest way to do this would be to use an EventToCommand[^] implementation and hook the RowEditEnding in there.ing in there.
|
|
|
|
|
Thanks Pete, I will try this out, but the example is for Win8 and I'm using Win7. Although I was able to get the code from EventToCommand class.
|
|
|
|
|
Yeah, there are plenty of EventToCommand implementations to have a look at.
|
|
|
|
|
Piotr Z wrote: but this is against MVVM Guidelines.
Personally I see nothing wrong with handling events in your code behind - the XAML and Code Behind should be working together to provide the user experience.
I'd personally handle the event in code behind and id I require something from the VM, do it there.
Just re-read the above and felt the last sentence wasn't clear.
What I mean is, handle the event in the code behind, then if I need the VM to perform some function, call an appropriate method from the code behind.
MVVM # - I did it My Way
___________________________________________
Man, you're a god. - walterhevedeich 26/05/2011
.\\axxx
(That's an 'M')
|
|
|
|
|
Can someone please explain to me what I'm doing wrong. My goal is to update a datagrid after entering values. For instance, I put 3 grades into 3 columns, then click a button and update the datagrid to achieve an average.
My C# code:
<pre>public partial class MainWindow : Window
{
public Student student = new Student();
public ObservableCollection<Student> studentData = new ObservableCollection<Student>();
public MainWindow()
{
InitializeComponent();
student.Name = "Whatever";
student.CalculusMarks = 0;
student.EnglishMarks = 0;
student.ProgrammingMarks = 0;
student.Percentage = 0;
studentData.Add(new Student { Name=student.Name, CalculusMarks = student.CalculusMarks, EnglishMarks = student.EnglishMarks, ProgrammingMarks = student.ProgrammingMarks, Percentage=student.Percentage});
datagrid1.DataContext = studentData;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
student.Percentage = (double)(student.CalculusMarks + student.EnglishMarks + student.ProgrammingMarks) * 100 / 300;
}
public class Student : INotifyPropertyChanged
{
private string _name;
private int _calculusMarks;
private int _englishMarks;
private int _programmingMarks;
private double _percentage;
public string Name
{
get
{
return _name;
}
set
{
_name = value;
OnPropertyChanged("Name");
}
}
public int CalculusMarks
{
get
{
return _calculusMarks;
}
set
{
_calculusMarks = value;
OnPropertyChanged("CalculusMarks");
}
}
public int EnglishMarks
{
get
{
return _englishMarks;
}
set
{
_englishMarks = value;
OnPropertyChanged("EnglishMarks");
}
}
public int ProgrammingMarks
{
get
{
return _programmingMarks;
}
set
{
_programmingMarks = value;
OnPropertyChanged("ProgrammingMarks");
}
}
public double Percentage
{
get
{
return _percentage;
}
set
{
_percentage = value;
OnPropertyChanged("Percentage");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}
My XML:
<<pre>Grid>
<DataGrid Name="datagrid1" AutoGenerateColumns="False" ItemsSource="{Binding}">
<DataGrid.Columns>
<DataGridTextColumn x:Name="NameCol" Header="Name" Width="*" Binding="{Binding Path=Name, NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged}"/>
<DataGridTextColumn x:Name="CalculusMarksCol" Header="Calculus" Width="*" Binding="{Binding Path=CalculusMarks, Mode=TwoWay, NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged}"/>
<DataGridTextColumn x:Name="EnglishMarksCol" Header="English" Width="*" Binding="{Binding Path=EnglishMarks, Mode=TwoWay, NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged}"/>
<DataGridTextColumn x:Name="ProgrammingMarksCol" Header="Programming" Width="*" Binding="{Binding Path=ProgrammingMarks, Mode=TwoWay, NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged}"/>
<DataGridTextColumn x:Name="PercentageCol" Header="Percentage" Width="*" Binding="{Binding Path=Percentage, Mode=TwoWay, NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged}"/>
</DataGrid.Columns>
</DataGrid>
<DockPanel LastChildFill="False">
<Button Content="Update" Height="50" Width="75" Margin="5" DockPanel.Dock="Bottom" Click="Button_Click" />
</DockPanel>
</Grid >
I have searched exhaustively and am still no closer to an answer. Thanks in advance.
|
|
|
|
|
Your datagrid does not bind a selecteditem and you are calculating on a new Student() which has no data.
Add a property of Student call SelectedStudent
Bind the SelectedItem to SelectedStudent - this will then be populated with the selected record from the grid.
Do your calculation on SelectedStudent.
Never underestimate the power of human stupidity
RAH
|
|
|
|
|
I am trying to read from an XML file and populate the data to a datagrid. All of the data is being populated, but I want to change the background color when a checkbox in a checkbox column is checked. This works when I select the checkbox with mouse, but not when reading from XML file, even though the checkbox shows true. Here is my code:
Datagrid Row Style:
<<pre>Style x:Key="dataGridRowStyle" TargetType="DataGridRow">
<Style.Triggers>
<DataTrigger Binding="{Binding Checked}" Value="True">
<Setter Property="Background" Value="LightGray"/>
</DataTrigger>
</Style.Triggers>
</Style >
Datagrid definition:
<<pre>DataGrid Name="amortizationSchedule" ItemsSource="{Binding}" AutoGenerateColumns="False" HorizontalContentAlignment="Center" CanUserAddRows="False" HorizontalScrollBarVisibility="Auto" RowStyle="{StaticResource dataGridRowStyle}" DockPanel.Dock="Top">
<DataGrid.Resources>
<Style TargetType="DataGridCell">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="DataGridCell">
<Grid Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="DataGridColumnHeader">
<Setter Property="HorizontalContentAlignment" Value="Center"/>
</Style>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridCheckBoxColumn Header="Paid?" Binding="{Binding Checked, Mode=TwoWay}" CanUserReorder="False" CanUserSort="False" CanUserResize="False"/>
<DataGridTextColumn Header="Payment #" Binding="{Binding monthlyPaymentNumber}" MaxWidth="150" Width="Auto" CanUserReorder="False" CanUserSort="False" CanUserResize="False" IsReadOnly="True"/>
<DataGridTextColumn Header="Payment Date" Binding="{Binding monthlyPaymentDate}" MaxWidth="150" Width="*" CanUserReorder="False" CanUserSort="False" CanUserResize="False" IsReadOnly="True"/>
<DataGridTextColumn Header="Payment Amount" Binding="{Binding monthlyPaymentAmount}" MaxWidth="150" Width="Auto" CanUserReorder="False" CanUserSort="False" CanUserResize="False" IsReadOnly="True"/>
<DataGridTextColumn Header="Principle Portion" Binding="{Binding monthlyPrinciplePortion}" MaxWidth="150" Width="*" CanUserReorder="False" CanUserSort="False" CanUserResize="False" IsReadOnly="True"/>
<DataGridTextColumn Header="Interest Portion" Binding="{Binding monthlyInterestPortion}" MaxWidth="150" Width="*" CanUserReorder="False" CanUserSort="False" CanUserResize="False" IsReadOnly="True"/>
<DataGridTextColumn Header="Ending Balance" Binding="{Binding monthlyEndingBalance}" MaxWidth="150" Width="*" CanUserReorder="False" CanUserSort="False" CanUserResize="False" IsReadOnly="True"/>
<DataGridTextColumn Header="Extra Payments Paid to Principle" Binding="{Binding monthlyExtraPaymentsToPrinciple}" Width="*"/>
</DataGrid.Columns>
</DataGrid >
C# Code behind, reading from XML:
if (File.Exists(myXMLPath))
{
DataSet ds = new DataSet();
dt = new DataTable();
dt.TableName = "dataTable";
ds.ReadXml(myXMLPath);
this.DataContext = ds.Tables[0].DefaultView;
}
|
|
|
|
|
Ok, so as everyone can see, I set the Datagrid to the DataSet, when I was trying to bind to the DataTable instead. Solution is to read the XML file back into the dataset, then assign the dataset back to the data table.
Thanks anyway for the support!
|
|
|
|
|
This isn't working:
<GridViewColumn Header="Category">
<GridViewColumn.CellTemplate>
<DataTemplate>
<Grid>
<TextBlock Name="txtBlah" Style="{StaticResource GridBlockStyle}" Text="{Binding Category.Name}"></TextBlock>
<ComboBox ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}},Path=DataContext.Categories}" DisplayMemberPath="Name" SelectedValuePath="Id" SelectedValue="{Binding Category.Id, Mode=TwoWay}" Style="{StaticResource GridEditStyle}" />
</Grid>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
When I change the combobox in edit mode it seems to work ok, but the textblock is not being updated. WTWaffles? This particular piece of functionality in WPF has always vexed me.
Cheers, --EA
|
|
|
|
|
Check the output window of the debugger for a binding error. Without the entire context of what you are doing I would guess the problem is the binding of the textblock. Inside the data template, the data context is the current row of the data set repeated for each item in the set.
So if you had a data context for the page which had a collection of categories and a collection of objects which had a category and a name, your combobox source is correct and will bind to the collection of categories. However, the selected value will bind to <row>.Category.Id where row is an object in the collection holding the rows withing the data context. Your bindings should be relative to that.
If your row contains a "category" object, your bindings are correct and the problem is likely that you aren't raising PropertyChanged for the Name property when you are changing the Id property.
If I could see the class that is your DataContext I could be more specific.
HTH
|
|
|
|
|
Funny, I just answered another question with this same suggestion. I am not seeing a binding path error of any sort.
The DataContext does have a category object and that object has an ID and a name.
So how do I implement the INPC for this scenario? I realize I could create a public category "SelectedCategory" and bind it to the SelectedItem of the ComboBox and then raise the OnPropertyChanged event when it changes, but what do I need to do in order to update the category name property of the SelectedItem of the ListView? Do I need to raise the OnPropertyChanged("SelectedItem") or what?
|
|
|
|
|