|
If you have a question about examples from an article, you should ask them on that article.
|
|
|
|
|
I am working on a WPF 4.0 app that calls to the back end via an MVC 4 Web API.
I have a view called Injuries. I have an InjuryEntity which contains an ObservableCollection of DocumentEntity.
I'm using an ObservableCollection because the WPF UI is bound as such:
<DataGrid Grid.Row="1"
Grid.Column="0"
Background="White"
ItemsSource="{Binding SelectedInjury.Documents}"
SelectedItem="{Binding SelectedDocument}"
AutoGenerateColumns="False"
FontSize="12"
FontWeight="Normal"
FontStyle="Normal"
IsReadOnly="True"
TabIndex="1200"
Height="130"
Margin="3">
When I call
InjuryEntity.Documents.Add()
everything works fine. I am able to save the data to the DB with no problem.
Now, when I call back into the API to get the Injuries, I get back null. The ENTIRE Injury entity is null, not just the documents.
If I make the ObservableCollection into List<>, then the data comes back fine.
I'm using ObservableCollection because in injury entity's Documents collection makes use of the Collection_Changed event so that I can do:
Documents = new List<InjuryDocumentsEntity>();
Documents.CollectionChanged += Documents_CollectionChanged;
private void Documents_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
RaisePropertyChanged("Documents");
}
This allows the data grid and other UI elements the be refreshed as soon as a collection item changes.
So, the problem appears to be that MVC 4 doesn't like ObservableCollection.
I've been Googling, but I'm not finding much help.
Can anyone shed some light on this?
Thanks
If it's not broken, fix it until it is
|
|
|
|
|
It sounds like a serialization problem.
Have the API return a List<> , and map that to an ObservableCollection<> in your view model.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
I'm working through the excellent book "Windows Presentation Foundation 4.5 Cookbook" by Pavel Yosifovich, trying to broaden my skill set. I'm at the 70% mark according to my Kindle Reader and still asking "why?" I don't normally like to copy the downloaded code because I learn a great deal by typing the code in and troubleshooting my errors. I finally threw in the towel with the code I will insert at the end of this post. My main aggravation is trying to use XAML to design graphical interfaces. I find it impossible to picture in my head anything but the simplest constructs. This may be a deficiency on my part but please, looking at the templates below created in App.xaml who can really tell what this is going to look like? Many lines of dense code that can't be viewed until the syntax is completely correct AND the template is used in a window.
I understand that there are tools like Blend which begs the question "Why isn't blend the default WPF design tool in Visual Studio?" Are there tools for visualizing, maybe even creating, templates?
I intend to work through the remaining chapters in this book and then explore the tools available in Blend and only use XAML to tweak. Is anyone else with me here?
Code:
<Application x:Class="CH08.CustomScrollBars.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ControlTemplate TargetType="RepeatButton" x:Key="repeatTransTemplate">
<Rectangle Fill="Transparent" />
</ControlTemplate>
<ControlTemplate TargetType="RepeatButton" x:Key="plainTemplate">
<Grid>
<ContentPresenter Margin="{TemplateBinding Padding}" />
</Grid>
</ControlTemplate>
<ControlTemplate TargetType="Thumb" x:Key="vthumbTemplate">
<Rectangle RadiusX="5" RadiusY="10" Stroke="{TemplateBinding BorderBrush}" StrokeThickness="{TemplateBinding BorderThickness}"
Fill="{TemplateBinding Background}" />
</ControlTemplate>
<ControlTemplate TargetType="ScrollBar" x:Key="verticalScrollBarTemplate">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Border BorderBrush="DarkBlue" BorderThickness="1" Background="LightBlue" Grid.Row="1">
<Track x:Name="PART_Track" IsDirectionReversed="True">
<Track.DecreaseRepeatButton>
<RepeatButton Command="ScrollBar.PageUpCommand" Template="{StaticResource repeatTransTemplate}" />
</Track.DecreaseRepeatButton>
<Track.IncreaseRepeatButton>
<RepeatButton Command="ScrollBar.PageDownCommand" Template="{StaticResource repeatTransTemplate}" />
</Track.IncreaseRepeatButton>
<Track.Thumb>
<Thumb Template="{StaticResource vthumbTemplate}" BorderBrush="Black" BorderThickness="1">
<Thumb.Background>
<LinearGradientBrush EndPoint="0,1">
<GradientStop Offset="0" Color="DarkGreen" />
<GradientStop Offset="1" Color="LightGreen" />
</LinearGradientBrush>
</Thumb.Background>
</Thumb>
</Track.Thumb>
</Track>
</Border>
<Viewbox>
<RepeatButton Command="{x:Static ScrollBar.LineUpCommand}" Template="{StaticResource plainTemplate}">
<Path Data="M 25,0 L 50,50 L 0,50 Z" Fill="Blue" />
</RepeatButton>
</Viewbox>
<Viewbox Grid.Row="2">
<RepeatButton Command="{x:Static ScrollBar.LineDownCommand}" Template="{StaticResource plainTemplate}">
<Path Data="M 25,50 L 0,0 L 50,0 Z" Fill="Blue" />
</RepeatButton>
</Viewbox>
</Grid>
</ControlTemplate>
<ControlTemplate TargetType="Thumb" x:Key="hthumbTemplate">
<Rectangle RadiusX="10" RadiusY="5" Stroke="{TemplateBinding BorderBrush}" StrokeThickness="{TemplateBinding BorderThickness}"
Fill="{TemplateBinding Background}" />
</ControlTemplate>
<ControlTemplate TargetType="ScrollBar" x:Key="horizontalScrollBarTemplate">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Border BorderBrush="DarkBlue" BorderThickness="1" Background="LightBlue" Grid.Column="1">
<Track x:Name="PART_Track" IsDirectionReversed="False">
<Track.DecreaseRepeatButton>
<RepeatButton Command="ScrollBar.PageLeftCommand" Template="{StaticResource repeatTransTemplate}" />
</Track.DecreaseRepeatButton>
<Track.IncreaseRepeatButton>
<RepeatButton Command="ScrollBar.PageRightCommand" Template="{StaticResource repeatTransTemplate}" />
</Track.IncreaseRepeatButton>
<Track.Thumb>
<Thumb Template="{StaticResource hthumbTemplate}" BorderBrush="Black" BorderThickness="1">
<Thumb.Background>
<LinearGradientBrush EndPoint="1,0">
<GradientStop Offset="0" Color="DarkGreen" />
<GradientStop Offset="1" Color="LightGreen" />
</LinearGradientBrush>
</Thumb.Background>
</Thumb>
</Track.Thumb>
</Track>
</Border>
<Viewbox>
<RepeatButton Command="{x:Static ScrollBar.LineLeftCommand}" Template="{StaticResource plainTemplate}">
<Path Data="M 0,25 L 50,50 L 50,0 Z" Fill="Blue" />
</RepeatButton>
</Viewbox>
<Viewbox Grid.Column="2">
<RepeatButton Command="{x:Static ScrollBar.LineRightCommand}" Template="{StaticResource plainTemplate}">
<Path Data="M 0,0 L 50,25 L 0,50 Z" Fill="Blue" />
</RepeatButton>
</Viewbox>
</Grid>
</ControlTemplate>
<Style TargetType="ScrollBar">
<Style.Triggers>
<Trigger Property="Orientation" Value="Vertical">
<Setter Property="Template" Value="{StaticResource verticalScrollBarTemplate}" />
</Trigger>
<Trigger Property="Orientation" Value="Horizontal">
<Setter Property="Template" Value="{StaticResource horizontalScrollBarTemplate}" />
</Trigger>
</Style.Triggers>
</Style>
</Application.Resources>
</Application>
|
|
|
|
|
Nah. "Cookbooks" are only useful if you already have a basic understanding of the overall subject matter (IMO), and you have a particular problem / question in mind.
In particular, the sample XAML you posted deals with "resources, styles, commanding, templating, triggers, ..."; stuff that is typically found in "later chapters".
One of the best books I found for learning WPF is: Illustrated WPF by Daniel Solis.
Also, there's a free tool out there for coding and visualizing XAML called XAMLPad that you may find useful:
http://msdn.microsoft.com/en-ca/library/vstudio/ms742398(v=vs.90).aspx[^]
It's been around for a while and may not have been updated, but it is still useful for learning.
I don't use a XAML visual designer. If you keep in mind that your XAML is just one big "tree"; that you can collapse and expand; and explore using the VS "Document Outline" window; then everything just falls nicely into place (after a while).
(BTW, the posted XAML is more-or-less like a "library" of templates; not particularly useful for visualizing a "form", per se. The templates / styles are used to alter the appearance of controls used in "real" forms / windows. Just fiddling with appearances; mostly.)
modified 17-Oct-14 17:29pm.
|
|
|
|
|
Programming is daunting in most shapes and sizes given code or starting from scratch. Biggest hurdle perhaps, choosing a platform and/or language. But ... wait a minute ... how would I be able to chose anything unless I had Visual Studio?
I suspect the place one needs to to go when they get confused then, is:
https://code.msdn.microsoft.com/[^]
Punch in the tools you have, get the samples, open them in VS.
Now tell us how difficult WPF is through VS.
|
|
|
|
|
Hmm. Not sure how you got the idea I didn't have Visual Studio. I've worked all the examples in VS and, while I can understand how they work I still think XAML has definite shortcomings as a graphical design language. As for opening samples in VS? I'm not sure what instructional value that has.
|
|
|
|
|
Caveat - I do LOB work and have limited skills or interest in building fancy UIs
I start of with a pencil and paper, rough out the shape of the view I want, identify the <grid>s I will need and then start coding. Until I have the basic shapes and controls laid out I don't even think about styles, resources or anything but where the controls are going to live.
You may recognise this style, break it down to small, easily understood pieces and start from there.
I have never bothered to learn blend I an more than happy with the VS display. A WPF view can be extremely complicated, as can a web page, part of the job.
You must remember you are looking at a finished view in the book, it may have taken the author a couple of hours to build and that will not include the pre built resources and styles he has pulled in.
Having been dipped in the sh*t pile of the current HTTP/CSS/JS stack I have to say WPF is AWESOME!
Never underestimate the power of human stupidity
RAH
|
|
|
|
|
Paper and pencil? My point exactly.
|
|
|
|
|
Yeah but I'm an old fart.
Never underestimate the power of human stupidity
RAH
|
|
|
|
|
I've found the key to creating template controls is to start with a working example - use Expression Blend to get the template code for an existing control. I then tweak the template until I get what I want, testing frequently. I can't imagine creating one from scratch, given that the required 'parts' values are undocumented.
Software Zen: delete this;
|
|
|
|
|
SteveHolle wrote: looking at the templates below created in App.xaml who can really tell what this is going to look like? Errrr, me. It's a fairly straightforward template after all. I appreciate your frustration, but it really does get a lot easier the more you do it.
Now, part of the reason we have XAML is that it's a relatively straightforward way to represent a UI, that keeps the actual "shape" of the UI decoupled from the actual implementation of your logic. The primary motivation for this was to allow designers and developers to work side by side on the same application - and yes, this does happen in some organisations, I wouldn't dream of releasing an app that didn't have UX designer support.
What helps is when you start to see that large complex templates are actually made up of smaller templates. So, for instance, if you want to restyle a scroll bar, you don't end up having to fully reimplement every part - perhaps you just want to change the colour of the thumb bar - in that case, you'd just tweak the Thumb (in the example you have, you could accomplish this using something like this):
<Style TargetType="Thumb">
<Setter Property="BorderBrush" Value="Black" />
<Setter Property="Thickness" Value="1" />
<Setter Property="Background">
<Setter.Value>
<LinearGradientBrush EndPoint="1,0">
<GradientStop Offset="0" Color="DarkGreen" />
<GradientStop Offset="1" Color="LightGreen" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Style>
|
|
|
|
|
Hi,
I’m trying to do something quite simple, I believe, but am very new to WPF and can’t figure it out. I want to display bank account details of a specific employee (which I select separately), and I want to let the user change those details if needed. My problem concerns specifically the following 3 tables:
Banks:
- BankID (PK)
- CountryID
- BankName
- ...
Countries:
- CountryID (PK)
- CountryName
- ...
BankAccounts:
- BankAccountID (PK)
- BankID
- ...
On my application’s MainWindow I have 2 ComboBoxes. I want to load the first one (cmbBankCountry) with a list of all the countries from ‘Countries’ table, and then automatically select the country which corresponds to the employee’s bank account.
Similarly, I want the second ComboBox (cmbBanks) to be loaded with the names of all the banks that are associated with the selected country, and here too, select automatically the bank associated with that employee’s bank account.
Of course, if the user changes the selection of the country for that bank account, the second ComboBox should be reloaded and display only the banks associated with the newly selected country.
All the data comes from an SQL database via Linq-To-SQL classes (dbml), which I generated to represent the database tables. I.e. I have a Bank class, a Country class, a BankAccount class, etc. defined in a DataContext that I declared as a Private Shared variable of Application. I also created a ReadOnly property called DBMain to access it.
So far I tried to tackle this task as follows:
To load the first Combobox with all the countries I placed the following code in the MainWindow_Loaded event:
Dim lstCountries As List(Of Country) = Application.DBMain.GetCountries()
cmbBankCountry.ItemsSource = lstCountries
cmbBankCountry.DisplayMemberPath = "CountryName"
cmbBankCountry.SelectedValuePath = "CountryID"
The GetCountries function looks like this:
Public Function GetCountries() As List(Of Country)
Dim lstCountry As List(Of Country) = (From c In Application.DBMain.Countries
Select c
).ToList
Return lstCountry
End Function
To load the second Combobox with the corresponding banks, I created an event that is triggered when the first Combobox’s selection (country) is changed:
Private Sub DisplayBanksForCountry()
Dim lstBanks As List(Of Bank) = Application.DBMain.GetBanks(cmbBankCountry.SelectedValue)
cmbBanks.ItemsSource = lstBanks
cmbBanks.DisplayMemberPath = "BankName"
cmbBanks.SelectedValuePath = "BankID"
End Sub
And the GetBanks function looks like this:
Public Function GetBanks(inCountryID As Integer) As List(Of Bank)
Dim lstBanks As List(Of Bank) = (From b In Application.DBMain.Banks
Where b.CountryID = inCountryID
Select b).ToList
Return lstBanks
End Function
Finally, the definition of the two ComboBoxes in the XAML file looks like this:
<ComboBox x:Name="cmbBankCountry" MinWidth="120" Grid.Row="0" Grid.Column="1" SelectedValue="{Binding Path=b.BankCountryID}" SelectionChanged="DisplayBanksForCountry"/>
<ComboBox x:Name="cmbBanks" MinWidth="120" Grid.Row="1" Grid.Column="1" SelectedValue="{Binding Path=b.BankID}"/>
In this “solution” the first ComboBox is working just fine. It is loaded with all the countries and shows automatically the country of the employee’s bank account.
However, when the Window is first loaded, the second ComboBox is empty. It is loaded with banks only after I change the selection of the first ComboBox. Obviously, this is what I asked it to do, but I was assuming (and hoping…) that the SelectionChanged event of the first ComboBox (cmbBankCountry) will occur when the ComboBox is set to display the account’s country by Binding. Unfortunately, that is not the case.
I guess that there is a very elegant way to do it via Binding between the two ComboBox, but my brain is still wired to the old Windows Forms, events oriented way of doing things.
Thank a lot in advance for any help!
|
|
|
|
|
|
|
I have a WPF applicaiton where the MainWindow class have <Window.CommandBindings> and <Window.InputBindings> so I can use CTRL + X, CTRL + C and CTRL + V commands.
The MainWindow contains a DataGrid where I want to select a row and copy the data in the row with the CTRL + C command. When a row is selected in the DataGrid the CTRL + C command stops working. CTRL + X and CTRL + V are still detected.
I have managed to reproduce this problem. Just copy and paste the code below, it should compile and run on the go.
Then do the following:
Press either CTRL + X, CTRL + C or CTRL + V you will get a popup window saying what command was activated.
Select a row in the DataGrid and then run CTRL + C. Nothing will happen.
MainWindow.XAML code
<Window x:Class="WpfApplication1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.CommandBindings>
<CommandBinding Command="Cut" Executed="btnCut_Click" />
<CommandBinding Command="Copy" Executed="btnCopy_Click" />
<CommandBinding Command="Paste" Executed="btnPaste_Click" />
</Window.CommandBindings>
<Window.InputBindings>
<KeyBinding Key="X" Modifiers="Control" Command="Cut" />
<KeyBinding Key="C" Modifiers="Control" Command="Copy" />
<KeyBinding Key="V" Modifiers="Control" Command="Paste" />
</Window.InputBindings>
<Grid>
<DataGrid Name="dgPersons" HorizontalScrollBarVisibility="Auto" AutoGenerateColumns="False" IsReadOnly="True" SelectionMode="Extended" GridLinesVisibility="None" Background="White" Margin="75,59,35,104">
<DataGrid.CellStyle>
<Style TargetType="DataGridCell">
<Setter Property="BorderThickness" Value="0" />
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
</Style>
</DataGrid.CellStyle>
<DataGrid.Columns>
<DataGridTextColumn Header="Name" Width="100" Binding="{Binding Name, Mode=OneTime}" />
</DataGrid.Columns>
</DataGrid>
</Grid>
</Window>
MainWindow.cs code
using System;
using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Input;
namespace WpfApplication1
{
public partial class MainWindow : Window
{
ObservableCollection<Person> persons = new ObservableCollection<Person>();
public MainWindow()
{
InitializeComponent();
Person person1 = new Person("Person1");
Person person2 = new Person("Person2");
Person person3 = new Person("Person3");
persons.Add(person1);
persons.Add(person2);
persons.Add(person3);
dgPersons.ItemsSource = persons;
}
private void btnCut_Click(object sender, ExecutedRoutedEventArgs e)
{
MessageBox.Show("CUT command activated");
}
private void btnCopy_Click(object sender, ExecutedRoutedEventArgs e)
{
MessageBox.Show("COPY command activated");
}
private void btnPaste_Click(object sender, ExecutedRoutedEventArgs e)
{
MessageBox.Show("PASTE command activated");
}
}
public class Person
{
string name;
public Person(string name)
{
this.name = name;
}
public string Name
{
get { return name; }
}
}
}
How do I get CTRL + C wrking when a row is selected in the DataGrid?
|
|
|
|
|
You are right that you won't get the MessageBox but it is handeling the copy command. Just add a TextBox and perform a paste. So I think the event is set to e.Handled before your event.
|
|
|
|
|
I'm confused about your answer:
* What do you mean by "add a TextBox".
* Why should I use a TextBox to solve this?
* Where should I add a TextBox?
* What has the paste command to do with this?
I only want the CTRL + C command to be detected in the MainWindow when a row is selected in the DataGrid. This has nothing to do what I want to copy and when I want to paste it.
|
|
|
|
|
That's what I am trying to tell you. In your current code it is detected. When you press CTRL+C the grid row is being copied. The textbox is just for testing. After the copy you can past your grid row there and see for your self that a CRTL+C copy was made.
|
|
|
|
|
What is your silverlight version ?
Because in the version 3 is not possible only in the 4 and the next versions
|
|
|
|
|
I have a viewbox consisting of 3 columns. First column can have a imported data items 0..1000. Second column is 2 buttons to move items from the 1st column to the 3rd column, or remove items from the 3rd column. Is there any way to keep the buttons in the middle of the grid as the user scrolls through the 1st column. Columns 1 and 3 are ContentControl types.
|
|
|
|
|
I suspect the viewbox contains a grid which has 3 columns! You are treating the buttons like collection items (column 1 and 3) I would move the buttons outside the collection (grid) control.
Never underestimate the power of human stupidity
RAH
|
|
|
|
|
I've been looking at how I can display validation failures in WPF.
The examples I've been looking at, typically create a style based on a control type.
Is the approach really to create a 'validation error' style for every control type? Isn't there a more generic approach?
Also some of my screens have grids, and I've worked out how I can either show the validation template per cell or the row, but I'm not sure I like the approach.
Is it possible to display the validation messages in a completely different location from the control(or controls), rather than adorned to them, say a textblock at the bottom of the screen.
I suppose the type of presentation I'd like is similar to the way Visual Studio has the errors window that gathers all the problems in one place.
|
|
|
|
|
Ok found this article showing how to do the style once, then use "based on" to apply it to other controls.
|
|
|
|
|
I have a report file connected to a data table.
DataTable dt = BizObject.GetDriversInspectionReportData(dvirs);
ReportDataSource reportDataSource = new ReportDataSource();
reportDataSource.Name = "DVIRReportData";
reportDataSource.Value = dt;
string reportFile = @"..\Reports\DVIRReport.rdlc";
ReportViewerView rvv = new ReportViewerView("Driver's Inspection Report", reportFile, reportDataSource);
rvv.ShowDialog();
When I get the data it comes back with multiple rows, yet when the report viewer comes up , there's always just one page. I'm not seeing any other pages.
Any idea what's wrong here?
Thanks
If it's not broken, fix it until it is
|
|
|
|
|