|
Sorry. I did not recognize that as a link.
When I add to .xaml
<pre>
<Grid>
<WindowsFormsHost>
<wf:MaskedTextBox x:Name="mtbDate" Mask="00/00/0000"/>
</WindowsFormsHost>
</Grid>
</pre>
I get this message "WindowsFormsHost is not supported in a Windows Presentation Foundation (WPF) project."
[not sure how to properly format code for this forum]
|
|
|
|
|
Ignore the chart, look up how to paint yourself in WPF. Simple hint, you use a for-loop to draw dots.
Was bloody easy in WinForms, so WPF should be easier.
Bastard Programmer from Hell
"If you just follow the bacon Eddy, wherever it leads you, then you won't have to think about politics." -- Some Bell.
|
|
|
|
|
I don't believe that's what the message said because you are not trying to host a "chart" as you posted; that's a "masked text box" you're fiddling with. Focus should be your primary objective.
xmlns:dv="clr-namespace:System.Windows.Forms.DataVisualization.Charting;assembly=System.Windows.Forms.DataVisualization"
<WindowsFormsHost x:Name="uxHost"
Grid.Row="1"
Grid.Column="0"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch">
<dv:Chart x:Name="uxChart" />
</WindowsFormsHost>
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
|
|
|
|
|
Solution:
Using the template on this web site - stackoverflow.com/questions/33756255/create-a-math-plot-in-c-sharp-xam
.xaml
<Canvas x:Name="gCanvasPlot0"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Margin="0,0,0,0"
Width="500"
Height="150" />
.cs
//------------------------------
private void AddPlot()
{
double dPI = Math.PI;
Polyline poXY = new Polyline {
Stroke = Brushes.Red
};
int iNumOfCycles = 3;
double dDeltaX = 0.01;
int iNumOfPoints0 = (int)(iNumOfCycles / dDeltaX);
for (int ii = 0; ii < iNumOfPoints0; ii++) {
double dX = ii * dDeltaX;
double dY = Math.Sin(2 * dPI * dX);
poXY.Points.Add(CorrespondingPoint(new Point(dX, dY), iNumOfCycles));
}
gCanvasPlot0.Children.Add(poXY);
}//AddPlot
//------------------------------
//------------------------------
private Point CorrespondingPoint(Point pt, int iNumOfCycles)
{
double dXmin = 0;
double dXmax = iNumOfCycles;
double dYmin = -1.1;
double dYmax = 1.1;
double dPlotWidth = dXmax - dXmin;
double dPlotHeight = dYmax - dYmin;
var poResult = new Point {
X = (pt.X - dXmin) * gCanvasPlot0.Width / (dPlotWidth),
Y = gCanvasPlot0.Height - (pt.Y - dYmin) * gCanvasPlot0.Height / (dPlotHeight)
};
return poResult;
}//CorrespondingPoint
//------------------------------
This works.
-- modified 18-Oct-21 11:02am.
|
|
|
|
|
Right. Now you can start thinking about axis labels, legends, titles, data sources, etc.
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
|
|
|
|
|
(shrug, should have posted this here before, newbie error)
I have a UI with a scrollviewer like this:
I want to scroll the viewer to the top when the ItemSource changes.
<ScrollViewer x:Name="Scroller" Grid.Row="2" Margin="0,0">
<StackPanel>
<ItemsControl x:Name="containers"
ItemsSource="{Binding Whatever, NotifyOnTargetUpdated=True}"
TargetUpdated="Containers_OnTargetUpdated">
</ItemsControl>
<StackPanel>
<ScrollViewer>
public partial class MyPage: UserControl
{
public MyPage()
{
InitializeComponent();
}
private void Containers_OnTargetUpdated(object? Sender, DataTransferEventArgs E)
{
var MyScroller = (ScrollViewer) this.FindName("Scroller");
MyScroller.ScrollToHome();
}
}
This works but it's probably not the best way to do it (ie. finding a control by name).
Can I pass the ScrollViewer "object" to the TargetUpdated callback/event ? so that I don't have to referencing it by name?
It seems clunky.
I don't know exactly what magic incantations I need to google for.
Thanks. M.
CI/CD = Continuous Impediment/Continuous Despair
|
|
|
|
|
Already answered in the C# forum:
Re: (xaml, wpf) ScrollViewer Binding confusion (beginner) - C# Discussion Boards[^]
private void Containers_OnTargetUpdated(object? sender, DataTransferEventArgs e)
{
var current = sender as DependencyObject;
var scroller = current as ScrollViewer;
while (scroller == null && current != null)
{
current = VisualTreeHelper.GetParent(current);
scroller = current as ScrollViewer;
}
if (scroller != null)
{
scroller.ScrollToHome();
}
}
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
I don't understand your apprehension about the "direct" approach ... or is this another "MVVM" thing?
private void Containers_OnTargetUpdated(object? Sender, DataTransferEventArgs E) {
this.Scroller.ScrollToHome();
}
The compiler recognize the name you gave to the ScrollViewer in the XAML (for that page / control); you don't need "reflection" in this case.
For other "public" cases, add a public "getter" for the control in question.
I assume you have some idea when the ItemsSource to the list is changed; set the scroll then if event handling is too confusing.
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
|
|
|
|
|
I'm working on a piece of UI where the user enters a dollar amount. The field is bound to a decimal.
Whenever I press the decimal point, here's a pic of what I get
Here's the xaml:
<TextBox Grid.Column="5"
Text="{Binding Entity.InvoiceAmount, StringFormat=C, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Margin="2"
Width="200"
Style="{StaticResource textBoxStyle}"
TextAlignment="Right"
IsEnabled="{Binding AreFieldsEnabled}"/>
The only way I can seem to change the decimal portion is to arrow over to it.
What's wrong here?
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
It's the same problem you had entering a percentage back in April:
Re: Format Percentage - WPF Discussion Boards[^]
Change UpdateSourceTrigger to LostFocus instead of PropertyChanged .
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
How did you remember that?? I totally forgot I posted that.
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
I've done this both ways, but I'd like to hear what you guys do....
Bind The Entity
Have the VM get an entity, or pass it in to the CTOR, store the entity to a property on the VM, and bind the View to the entity's properties.
With this approach, the only way to 'undo' is to requery the data, but it's easier to set up and maintin, IMHO.
Bind To VM Properties
Have seperate properties on the VM for everything bound on the View. Load those properties from an entity. Then, when saving, create or update an entity from the VM and save it.
To Undo, simply reload the VM's properties from the entity. But it's another set of properties on the VM mirroring those on the entity.
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
I always had the properties declared in the VM, loaded from the model which reflect a view from the database. However I have a tool that generates the code from the database to the model and a region in the VM so refactoring effort is minimal.
Never underestimate the power of human stupidity -
RAH
I'm old. I know stuff - JSOP
|
|
|
|
|
The first approach is really a "cheating" MVVM approach. You might as well not bother having the VM in there at this point because your view is almost binding directly to the model with only the thinnest of abstractions sitting on top. One of the purposes of the VM is that it is there to act as a guard for your model; suppose that I have a requirement that a model can only be saved if field_A is set and then field_B contains a value from 0 to 10, but if field_A isn't set then field_B can accept anything from 0 to 30. The VM is the place to ensure that this guardrail is enabled; it ensures the model is always pure before you attempt to save it.
|
|
|
|
|
Pete O'Hanlon wrote: The VM is the place to ensure that this guardrail is enabled
Global validation rules should probably be enforced in the entity and the database as well wherever possible.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
I use all "three"; depending on the situation. And sometimes all 3 at the same time.
There's the POCO; no "brains"; just getters and setters.
Then there are "is valid" getters, etc.; the "smart" POCO.
Then there are the Observable collections of same; bound to a lists and views at the same time ... with the selected POCO showing in a view ... which could be controls on a map.
Binding the POCO could be simple a DataContext assignment; or it is completely or partially aided by view getters into the POCO (view model).
e.g. if I want to show "full name" and I have "first" and "last", the obvious thing is to make a "full name" getter ... in the POCO or in the view. Variants of the ToString() override. The list goes on.
"Classic" MVVM is only one strategy ... and a very narrow one at that.
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
|
|
|
|
|
When I instantiate a VM, it typically instantiates the model on its own, which retrieves the data (from a database, xml, or json file).
If the requirements call for modifying/saving the data, I keep the model around in a protected property inside the viewmodel.
Most of the time, I set the data context to the form, and bind controls to the viewmodel(s) and various other properties. I don't think I've ever set the data context to a specific viewmodel because that just means more typing.
".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 am working on an app that is organized sort of as a browser with the frame/page construct. I ran across an interesting behavior that I can not find documented. When you use the Initialize event, it gets executed when the page is instantiated. When you use the Loaded event, it gets executed every time the page becomes content of the frame. It makes sense and is sort of alluded to in the Microsoft documentation, but the implication is easily missed as it applies to frame/page.
I have run across other interesting aspects of fame/page that are not clearly documented. Is there a good article or book that really describes the frame/page construct? Everything I have found is rather superficial just giving the highlights or stressing navigation. It should be at least 10 pages long and could be a book of well over 100 pages.
So many years of programming I have forgotten more languages than I know.
|
|
|
|
|
User controls (and Tabs) do the same thing: repeatedly fire the Loaded event. It's not an issue, unless you're initializing in the Loaded event. In those cases, I use an "is Intialized" flag to avoid redundant processing (among other things).
Note that "Loaded" doesn't mean it was being created (every time); it runs every time the user control becomes "active" / available.
This information is only available to those that ferret it out themselves; as you have just done.
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
|
|
|
|
|
I like that phrase, "ferret it out". It is a common idiom. I brings to mind the furry little animal that seems to not have a spine and can get into all kinds of places. Per Wikipedia, The name "ferret" is derived from the Latin furittus, meaning "little thief". In this case wiggling around a lot and stealing results from obscure references.
So many years of programming I have forgotten more languages than I know.
|
|
|
|
|
I have a Purchase Order Creation window that has dialogs to allow the user to add items to the PO. The main view model is AddEditPurchaseOrderViewModel. There are different types of items such as Equipment, Lumber, Hardware, etc, that can be added and each has its own View and VM.
In each window the user must select the item they want (Equipment, Hardware, etc) and any number of Sequence Sheets. For each Sequence Sheet selected a new line item created an added to the Purchase Order. So, if the user selects Lumber for 3 Sequence Sheets, then 3 Lumber line items are added to the PO. To create the line items I am cloning the initial line item, changing a few properties on it, and adding it to the PO.
Here's a pic of what I'm working on.
All of a sudden now, my Clone class is throwing bizzare errors. It's telling me that the dialog's viewmodel is not serializable. It doesn't need to be - the entity I get from the VM's is what's being cloned.
Here's my AddPOItem Method
private void AddPOItemExecuted()
{
_PurchaseOrderDialogBase vm = null;
var poItem = new PurchaseOrderItemEntity
{
PurchaseOrderHeaderId = PurchaseOrderHeader.Id,
JobId = PurchaseOrderHeader.JobId,
PurchaseOrderKind = PurchaseOrderHeader.PurchaseOrderKind
};
var args = new AddEditPOItemArgsModel
{
LocationId = SelectedLocation.Id,
POItem = poItem,
SequenceSheets = _sequenceSheets,
POType = PurchaseOrderHeader.PurchaseOrderType
};
switch (PurchaseOrderHeader.PurchaseOrderType)
{
case Entities.Enums.PurchaseOrderType.Equipment:
if (SelectedVendor.Id == AppCore.DNACompany.Id ||
SelectedVendor.Id == AppCore.ParagonCompany.Id)
{
vm = new AddEditEquipmentFromInventoryViewModel(args, "Add Equipment Item");
}
else
{
vm = new AddEditPOItemViewModel(args, "Add Equipment Item", SelectedVendor.Id);
}
break;
case Entities.Enums.PurchaseOrderType.Lumber:
if (SelectedVendor.Id == AppCore.DNACompany.Id ||
SelectedVendor.Id == AppCore.ParagonCompany.Id)
{
vm = new AddEditLumberFromInventoryViewModel(args, "Add Lumber Item");
}
else
{
vm = new AddEditLumberPOItemViewModel(args, "Add Lumber Item");
}
break;
}
if (vm != null)
{
DialogResultEx dialogResult = DialogService.ShowDialog(vm, typeof(MainWindowView));
if ((bool)dialogResult.DialogResult)
{
if (PurchaseOrderHeader.PurchaseOrderType == Entities.Enums.PurchaseOrderType.Equipment ||
PurchaseOrderHeader.PurchaseOrderType == Entities.Enums.PurchaseOrderType.Tools)
{
poItem.EntityState = EntityState.New;
PurchaseOrderHeader.PurchaseOrderItems.Add(poItem);
}
else
{
var selectedSheets = vm.SequenceSheetInfos.Where(x => x.IsSelected).ToList();
foreach (var selectedSheet in selectedSheets)
{
var newItem = poItem.Clone();
newItem.JobSequenceSheetId = selectedSheet.JobSequenceSheetId;
newItem.EntityState = EntityState.New;
newItem.PlanElevation = selectedSheet.JobLotInfo;
PurchaseOrderHeader.PurchaseOrderItems.Add(newItem);
}
}
}
}
}
and my Clone method
public static T Clone<T>(this T source)
{
if (!typeof(T).IsSerializable)
{
throw new ArgumentException("The type must be serializable.", nameof(source));
}
if (ReferenceEquals(source, null))
{
return default;
}
using (Stream stream = new MemoryStream())
{
IFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, source);
stream.Seek(0, SeekOrigin.Begin);
return (T)formatter.Deserialize(stream);
}
}
And here's a pic of the error. Not that the type passed in is PurchaseOrderItemEntity, which IS serializable, yet the exception tells me the AddEditPOItemViewModel is not serializable. Th is doesn't make any sense. I get this regardless of which dialog I opened and the message shows that VM's name.
Anyone have any idea what's going on?
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
Based on the error, it looks like your PurchaseOrderItemEntity has gained a reference to your AddEditPOItemViewModel instance somehow. You'll need to dig into its properties to find out where that reference is, and mark the reference as "not serialized".
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Thanks, but I already checked into that. No luck.
So this morning, on a hunch, I replaced my clone method with this
public static T Clone<T>(this T source) where T : class
{
var clonedJson = JsonConvert.SerializeObject(source);
return JsonConvert.DeserializeObject<T>(clonedJson);
}
and it now works. The previous clone code I posted was working up until something changed this week when it stopped working. Strange.
Thanks for your help.
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
Overview
I have a DataGrid with a DataGridTemplateColumn with a combobox inside it. The combobox is populated by enums using an ObjectDataProvider. The ComboBox DataTemplate renders the enum items hyperlinks.
Problem
I want to disable hyperlinks that should not be clickable based on some value on the entity. I'm not sure how to go about this.
Here is a screenshot of the grid
and here's the XAML
<DataGridTemplateColumn Header="Actions"
Width="220">
<pre>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox Grid.Row="0"
Grid.Column="1"
ItemsSource="{Binding Source={StaticResource actions}}"
Style="{StaticResource comboBoxStyle}"
IsEnabled="True"
Width="200"
Margin="2">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock>
<Hyperlink Style="{StaticResource HyperlinkStyle}">
<TextBlock Text="{Binding Converter={StaticResource enumDescConverter}}"
FontSize="14"/>
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<i:InvokeCommandAction Command="{Binding ElementName=dispatchControl, Path=DataContext.ExecuteActionCommand}"
CommandParameter="{Binding}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Hyperlink>
</TextBlock>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
What's wrong with binding the IsEnabled property on the Hyperlink to a property on your view-model?
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|