|
Why didn't I thought of that.
I tried it yesterday and it worked great. Thanks!
|
|
|
|
|
I'm building a WPF DataGrid. Nothing too hard there. However, I will have groups of columns that present Vendors. I want to put a group "header" above header section and have it scroll left & right with the grid's content.
See this image for my idea.
So the question is how to move the group header when the grid's data is scrolled?
Thanks!
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
Maybe you could try something like the solution suggested here:
WPF multi-column super header[^]
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
I need to automatically generate a WPF DataGrid at runtime. Some of the columns will be known, and some will be added based off user selections. In all cases, I'll know the data types. The column definitions will all be rows in some table, allowing me to create any number of columns.
The problem that I'm going to run into is binding. Since there will be an unknown number of columns, I can't create an "concrete" entity to bind to. So, the real question here is how to represent the data when I don't know all the columns.
I came across some examples of ExpandoObject usage and put together this sample:
static void Main(string[] args)
{
var x = new ExpandoObject() as IDictionary;
x.Add("NewProp", "Hello World!");
IDictionary propertyValues = x;
foreach (var property in propertyValues.Keys)
{
Console.WriteLine(String.Format("{0} : {1}", property, propertyValues[property]));
}
dynamic expando = new ExpandoObject();
expando.SomeStringProp = "C";
expando.SomeNumberProp = 12;
expando.MyMethod = new Func(() =>
{
return 55;
});
Console.WriteLine(expando.SomeStringProp);
Console.WriteLine(expando.SomeNumberProp);
Console.WriteLine(expando.MyMethod());
Console.ReadLine();
}
I'm concerned about performance here. If anyone has a better way I'd like to hear about it.
Thanks!
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
modified 19-Mar-21 16:58pm.
|
|
|
|
|
How about loading the data into a DataTable and binding the grid to the table's .DefaultView property?
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Ya, a table would be easier to build. I'll look into it.
Thanks!
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
Ok, I'm stuck here. I can see rows - no data just the highlight - and no columns.
What am i doing wrong??
XAML
<DataGrid Grid.Row="1"
AutoGenerateColumns="False"
ItemsSource="{Binding BidBudgetData.DefaultView}"/>
ViewModel
private DataTable _BidBudgetData;
public DataTable BidBudgetData
{
get { return _BidBudgetData; }
set
{
if (_BidBudgetData != value)
{
_BidBudgetData = value;
RaisePropertyChanged("BidBudgetData");
}
}
}
private void CreateBidBudgetTable()
{
var bidBudgetData = new DataTable();
bidBudgetData.Columns.Add("Plan Type", typeof(string));
bidBudgetData.Columns.Add("Living Sq Ft", typeof(decimal));
foreach (var planType in ProjectPlanTypeSummaries.OrderBy(x =>x.Plan).ThenBy(x => x.Elevation))
{
DataRow row = bidBudgetData.NewRow();
row["Plan Type"] = $"{planType.Plan}{planType.Elevation}";
row["Living Sq Ft"] = planType.LivingSqFt;
bidBudgetData.Rows.Add(row);
}
BidBudgetData = bidBudgetData;
RaisePropertyChanged("BidBudgetData");
}
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
You've set AutoGenerateColumns to false , but you haven't manually defined any columns in the DataGrid .
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Yup. I'm an idiot. I spent hours trying to figure out why I'm not seeing anyting.
Thanks!
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
Using VS2019, .Net framework 4.72:
I wrote a simple app that has a collection class (derived from ObservableCollection ) of items (that inherit from INotifyPropertyChanged ). I'm specifying 5 items to process.
Each of these items has a DoWork method that simply sits and spins for a randomly selected amount of time (from 1 to 30 seconds). While an item is "spinning", it updates a Progress property, as well as a Status property. The updates to these properties are intended to update the UI.
The observable collection class contains a method that does the following:
public void Start()
{
try
{
var list = this.Where(x=>x.Status == WorkerStatus.NotStarted);
Parallel.ForEach(list, this.options, worker=>
{
worker.DoWork(options.CancellationToken);
});
}
catch (OperationCanceledException ex)
{
if (ex != null) { }
}
}
I'm not getting any exceptions, but the UI updates appears to reflect item status updates all at the same time.
In an attempt to fix the update issue, I call this method from the Progress and Status property set method
private void DispatcherNotify(params string[] propertyNames)
{
Dispatcher.CurrentDispatcher.Invoke(()=>
{
foreach(string name in propertyNames)
{
this.NotifyPropertyChanged(name);
Debug.WriteLine("{0} - {1}", this.IDName, name);
}
});
}
I have verified that this method is indeed being called as expected, but the UI isn't updating (each "item" has its own UI component that is supposed to be updated).
The UI status update is handled by a converter, and that converter is called for all five items , but only when all 5 items have finished processing.
What am I doing wrong?
".45 ACP - because shooting twice is just silly" - JSOP, 2010 ----- You can never have too much ammo - unless you're swimming, or on fire. - JSOP, 2010 ----- When you pry the gun from my cold dead hands, be careful - the barrel will be very hot. - JSOP, 2013
|
|
|
|
|
I would've created an ObservableCollection of "user controls" (that implement INotify).
I then invoke PropertyChanged on the user controls; which could be hosted in any type of "panel" type control.
It was only in wine that he laid down no limit for himself, but he did not allow himself to be confused by it.
― Confucian Analects: Rules of Confucius about his food
|
|
|
|
|
The items are bound to a user control.
".45 ACP - because shooting twice is just silly" - JSOP, 2010 ----- You can never have too much ammo - unless you're swimming, or on fire. - JSOP, 2010 ----- When you pry the gun from my cold dead hands, be careful - the barrel will be very hot. - JSOP, 2013
|
|
|
|
|
But you appear to be scoping the property changed to the collection, not the items.
It was only in wine that he laid down no limit for himself, but he did not allow himself to be confused by it.
― Confucian Analects: Rules of Confucius about his food
|
|
|
|
|
The user control element that is supposed to show the update is bound to the item (which is the data context). The UI does in fact update, but not while any of the 5 items is processing
".45 ACP - because shooting twice is just silly" - JSOP, 2010 ----- You can never have too much ammo - unless you're swimming, or on fire. - JSOP, 2010 ----- When you pry the gun from my cold dead hands, be careful - the barrel will be very hot. - JSOP, 2013
|
|
|
|
|
I want to collapse or expand all TreeView nodes under parent node if user holds down Left Control key and presses left mouse button on expansion arrow of tree view.
How do you do this in WPF? It's not as obvious as it was in WinForms.
|
|
|
|
|
|
As Gerry mentioned, you need to hook up a handler for the mouse click and check the status of the CTRL key.
You then go through all your child ViewModels and flip the property you databound to the IsExpanded property.
This is how you can databind the IsExpanded property (and take IsSelected along for the ride if you need it - makes it VERY easy to select an item programmatically):
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="IsExpanded" Value="{Binding Path=IsExpanded, Mode=TwoWay}"/>
<Setter Property="IsSelected" Value="{Binding Path=IsSelected, Mode=TwoWay}"/>
</Style>
</TreeView.ItemContainerStyle>
In case you do not have a view model for your tree items you have two options:
1. Switch to WinForm
2. Introduce the view model
I supposed you could also try calling methods on the tree view control itself to find it's children, but it will be a LOT more code than the viewmodel, specifically when it start delay loading and virtualizing etc. WPF was designed for a ViewModel, and going against that is always asking for pain.
|
|
|
|
|
Hi,
I want to create a project with AvalonDock and MVVM based on the example of AvalonDock and MVVM of Ashley Davis.
I want to use the AValonDock.ManagedContent class (AvalonDock component) but in the Dirkster AvalonDock package (Dirkster99 · GitHub) the ManagedContent class in not present.
Is there a workaround or an equivalent class ?
Thanks for the answers.
|
|
|
|
|
It's been 10 years ... time marches on.
AvalonDock and MVVM
It was only in wine that he laid down no limit for himself, but he did not allow himself to be confused by it.
― Confucian Analects: Rules of Confucius about his food
|
|
|
|
|
Hi Gerry,
Thanks for the answer.
I'm read the "AvalonDock and MVVM" project of Ahsley Davis. He uses ManagedContent class of Avalon (especially in dico Dictionary<object, managedcontent=""> contentMap, ..),
but in the new AvalonDock version (of Dirkster99 Avalon free support release),
i notice that this class MangedContent does not exist.
If there is no bypass, I will do it another way (based on the Avalon example MVVMTestApp that comes with the AvalonDock source code).
Regards.
|
|
|
|
|
I'm using MahApps in my app. The data grid's column header style looks like this.
So I added this to my cell headers:
<DataGridTextColumn.HeaderStyle>
<Style TargetType="DataGridColumnHeader">
<Setter Property="HorizontalContentAlignment"
Value="Center" />
</Style>
</DataGridTextColumn.HeaderStyle>
The problem is that now the column headers have lost their style. It now looks like this
How can I apply the header alignment without loosing my grid styling?
Thanks
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
Use BasedOn.
It was only in wine that he laid down no limit for himself, but he did not allow himself to be confused by it.
― Confucian Analects: Rules of Confucius about his food
|
|
|
|
|
So I have this ListView , and I want to make a specific column have a different font family, so I tried setting the CellTemplate for the column. Because of the architecture of the app, I have to apply this template in the C# code.
I tried :
- Creating a resource like so:
<DataTemplate x:Key="PAScodeGridCell" >
<TextBlock Text="{Binding}" FontFamily="Consolas" />
</DataTemplate>
and was setting it like so:
column.CellTemplate = (DataTemplate)WpfCommon.Globals.XamlReaderLoad("PAScodeGridCell"); It found the template in the resource file, and set it to the CellTemplate property, but the font in that column wasn't Consolas.
Next, I tried so I tried specifying the template as a string in the c# code like so:
readonly string _CELL_TEMPLATE_ = string.Concat( "<DataTemplate xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\">",
"<TextBlock ",
"Text=\"{{Binding Path=PAScode}}\" ",
"FontFamily=\"Consolas\" /></DataTemplate>", and set the property like so
column.CellTemplate = (DataTemplate)XamlReader.Load(xaml);
The result was no different.
By all rights, both methods should have worked. I inspected the visual tree while the app was running and it's as if the specified template wasn't applied at all.
What am I don't wrong?
".45 ACP - because shooting twice is just silly" - JSOP, 2010 ----- You can never have too much ammo - unless you're swimming, or on fire. - JSOP, 2010 ----- When you pry the gun from my cold dead hands, be careful - the barrel will be very hot. - JSOP, 2013
|
|
|
|
|
|
I think I posted the wrong snippet for the first attempt. I used FindResource there.
No matter which way I tried it, the CellTemplate showed that it was set, but the column did not reflect the settings I was trying to set.
".45 ACP - because shooting twice is just silly" - JSOP, 2010 ----- You can never have too much ammo - unless you're swimming, or on fire. - JSOP, 2010 ----- When you pry the gun from my cold dead hands, be careful - the barrel will be very hot. - JSOP, 2013
|
|
|
|