|
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
|
|
|
|
|
I am using the standard report that ships with VS 2010 (rdlc).
I don't see a checkbox in the toolbox. Can I somehow get a checkbox on a report using the standard reporting?
If it's not broken, fix it until it is
|
|
|
|
|
A CheckBox is an interactive element, but a report is static, hence it does not make sense.
If you want to display a Boolean value in that style, you could use images, and add the "checked" image for true, the "unchecked" image for false instead.
|
|
|
|
|
Bernhard Hiller wrote: A CheckBox is an interactive element
True, but you still might want to print a checkmark..
I added a Rectangle with a checkmark image inside. I set the image's Visible based on the bool field in the data.
If it's not broken, fix it until it is
|
|
|
|
|
Apologies if the question isn't clear, I'm struggling to find the right terminology.
I have a entity that has properties which are the same entity i.e.:
public class Unit
{
public int Id {get;set;}
public string Name {get;set;}
public int ParentUnitId {get;set;}
}
On my WPF form I'd like a combobox for the user to select which Unit is the ParentUnitId.
So far I've gotten it by using a List, but this a) doesn't update if you add a new Unit, b) doesn't seem 'right', I feel like I should be able to achieve this with binding alone.
<ComboBox ItemsSource="{Binding}"
DisplayMemeberPath="Name"
SelectedValuePath="Id"
SelectedValue="{Binding Path=ParentUnitId}"/>
If I just have my XAML starting the ComboBoxes ItemSources are the same source as the Form, then they act as filters/selectors and the whole form moves to that record.
I'm using a CollectionViewSource as the DataContext for my Window.
|
|
|
|
|
Don't use a List<Unit> as the collection behind your ItemsSource use ObservableCollection<Unit> as this raises change notifications when the number of items in the list changes. As far as the rest of your question goes, I'm really not clear what you're trying to achieve here.
|
|
|
|
|
Yea I understand about the List / ObservableCollection bit.
I'll have another go
On my form, which allows you enter new units and change their details, one of the details is 'which is the parent unit'. This is a combobox, which should allow the user to select from the list of units.
Its the correct setup of this combobox that I'm having problems with.
I *think* I should be able to achieve this with pure XAML, but I'm not sure how.
As I think the pure XAML solution will also have the advantage that if a new unit is added on the form, the combobox lists will all contain the new unit (as they're all the same source in some sense), which my current solution of a List wont have. And unless I've missed something, just changing List to ObservableCollection wont resolve that will it?
|
|
|
|
|
It would help if you could show us your ViewModel. That way I should be able to get a clearer idea. As it is, I can see 3 or 4 things that you could be asking for and I'd hate to send you up a blind alley. Oh, and if you need to add new items, you definitely need the OC. A list will not notify the ComboBox that there are new items.
|
|
|
|
|
Ah, well right now we're not using VM. There's not a massive amount of experience, so we want to start slow and with what we're used to, so thats CodeBehind.
I've pasted, the XAML, Code Behind and entity here (given the size didn't seem sensible to flood the forum)
Pastie[^]
So each Unit has three fields (BusinessAreaId, DivisionalUnitId, ParentUnitId), that also reference a Unit, so I would like 3 comboboxes each with a list of units inside, and ideally as you add units, then the combobox items also grow.
My current ef entity load code is:
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += (s, ev) =>
{
this.Dispatcher.Invoke(new Action(() =>
UIHelper.ProgressBarRun(true)));
context.Units.Load();
context.UnitTypes.Load();
unitNames = new ObservableCollection<UnitName>(
context.Units.Local.Select(f => new UnitName() { Id = f.Id, Name = f.Name }));
};
worker.RunWorkerCompleted += (s, ev) =>
{
viewSource.Source = context.Units.Local;
unitTypeIdComboBox.ItemsSource = context.UnitTypes.Local;
businessAreaIdComboBox.ItemsSource = unitNames;
divisionalUnitIdComboBox.ItemsSource = unitNames;
parentUnitIdComboBox.ItemsSource = unitNames;
this.Dispatcher.Invoke(new Action(() =>
{
UIHelper.ProgressBarRun(false);
navFirstButton.RaiseEvent(new RoutedEventArgs(Button.ClickEvent));
}));
};
worker.RunWorkerAsync();
|
|
|
|
|