Skip to content

Add Platinum & Ducat counting to 'Auto Add' window#411

Open
occluder wants to merge 6 commits intoWFCD:masterfrom
occluder:plat-ducat-summary
Open

Add Platinum & Ducat counting to 'Auto Add' window#411
occluder wants to merge 6 commits intoWFCD:masterfrom
occluder:plat-ducat-summary

Conversation

@occluder
Copy link

@occluder occluder commented Feb 17, 2026

Display cumulative Platinum and Ducats earned in 'Auto Add' view by; adding TotalPlatinum and TotalDucats to AutoAddViewModel.
7LHtle1Owl

Totals update automatically as items are added/removed.

I am however running into an issue with updating values when a relic reward option is changed (see line 118 here). So far, have not had any success investigating what is causing this, so this PR will be a draft until the issue and considerations below are addressed. Any help with this would be appreciated.

Considerations

  • Does this contain a new dependency? No
  • Does this introduce opinionated data formatting or manual data entry? Maybe (See changes to WFInfo/AutoCount.xaml)
  • Does this pr include updated data files in a separate commit that can be reverted for a clean code-only pr? No
  • Have I run the linter? No
  • Is is a bug fix, feature request, or enhancement? Enhancement

Summary by CodeRabbit

  • New Features
    • Real-time aggregate totals for Platinum and Ducats added and displayed in the UI.
    • Totals update live as items are added, removed, or changed.
  • UI
    • Layout updated to prominently show totals alongside Save and Dismiss actions.
    • Data grid selection now updates immediately for a more responsive experience.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 17, 2026

📝 Walkthrough

Walkthrough

This change introduces aggregate totals tracking for Platinum and Ducats in the AutoAdd system. The ViewModel now maintains and updates these totals dynamically when items are added, removed, or when their options change. The UI is updated to display these calculated totals alongside associated icons.

Changes

Cohort / File(s) Summary
Totals Tracking Logic
WFInfo/AutoAddViewModel.cs
Added TotalPlatinum and TotalDucats properties with automatic updates. New UpdateTotalsForOptionChange() method recalculates totals when options change. Modified addItem() and removeItem() methods to trigger total updates. AutoAddSingleItem now propagates option changes to parent ViewModel via _parent reference.
Totals Display
WFInfo/AutoCount.xaml
Redefined bottom grid layout from 2 to 3 columns. Replaced header label with new StackPanel displaying total Platinum and Ducats with icons. Repositioned "Save all" and "Dismiss all" buttons into separate columns. Updated DataGrid binding with UpdateSourceTrigger=PropertyChanged.

Sequence Diagram

sequenceDiagram
    participant UI as AutoCount UI
    participant Item as AutoAddSingleItem
    participant VM as AutoAddViewModel
    
    UI->>Item: Change option selection
    Item->>Item: Detect option change<br/>capture previousOption
    Item->>VM: UpdateTotalsForOptionChange(previousOption, newOption)
    VM->>VM: Read previous option data<br/>(if exists)
    VM->>VM: Subtract from TotalPlatinum<br/>& TotalDucats
    VM->>VM: Read new option data
    VM->>VM: Add to TotalPlatinum<br/>& TotalDucats
    VM->>VM: Raise property changed<br/>notifications
    VM->>UI: Display updated TotalPlatinum<br/>& TotalDucats
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 A rabbit hops through code so bright,
Tallying platinum, ducats right,
When options shift and items change,
The totals dance and rearrange,
Now UI shows what's in the mix!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and concisely describes the main enhancement: adding platinum and ducat counting functionality to the Auto Add window, which is the core purpose of the changes.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@D1firehail
Copy link
Contributor

Adding UpdateSourceTrigger=PropertyChanged to the binding fixes it. Found it in this StackOverflow answer.

Mode=TwoWay is the default behaviour of SelectedItem, so you don't need to explicitly state it. It's fine to keep for the sake of readability, though.

@occluder
Copy link
Author

occluder commented Feb 17, 2026

Thank you for the remedy to my headache, I was jumping around in code trying to debug it 😅

I believe the functionality to be complete now, so I will open the PR for review. Code has to be looked at, as I do not fully understand what the considerations ask of me

@occluder occluder marked this pull request as ready for review February 17, 2026 18:18
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
WFInfo/AutoAddViewModel.cs (2)

100-100: Public mutable field _parent with underscore prefix — consider encapsulating.

By convention, underscore-prefixed members are private backing fields. Exposing _parent as a public field allows any caller to mutate it. Consider making it a read-only property set via the constructor, or at least internal.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@WFInfo/AutoAddViewModel.cs` at line 100, The public mutable field _parent on
AutoAddViewModel breaks encapsulation and uses an underscore prefix reserved for
private backing fields; change _parent to a private readonly field or expose it
as a read-only property (e.g., Parent) set via the AutoAddViewModel constructor
(or at minimum mark it internal instead of public) so external callers cannot
mutate it directly and the naming follows conventions; update any callers to use
the new constructor/property.

134-149: Constructor relies on _parent being null when ActiveOption is first set — fragile ordering.

ActiveOption is assigned at line 141 before _parent is set at line 147. This works today because the null-conditional _parent?.UpdateTotalsForOptionChange(...) is a no-op, and addItem separately accounts for the initial totals. However, if anyone reorders these two assignments (e.g. setting _parent first), the totals will be double-counted.

Consider moving _parent = parent; before the ActiveOption assignment and removing the redundant UpdateTotalsForOptionChange call in addItem, or add a brief comment explaining the required ordering.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@WFInfo/AutoAddViewModel.cs` around lines 134 - 149, Constructor
AutoAddSingleItem sets ActiveOption before assigning _parent which makes
behavior ordering-dependent; move the assignment _parent = parent to before
setting ActiveOption inside AutoAddSingleItem (or alternatively remove the
redundant call to UpdateTotalsForOptionChange inside addItem), so that
ActiveOption's setter can safely call _parent?.UpdateTotalsForOptionChange
without relying on null ordering; update or add a short comment on the
constructor explaining the intended ordering if you choose to keep the current
sequence.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@WFInfo/AutoAddViewModel.cs`:
- Around line 64-95: UpdateTotalsForOptionChange currently casts the result of
Main.dataBase.marketData.GetValue(previousOption/newOption) to JObject and then
indexes into it, which throws a NullReferenceException when GetValue returns
null; update the method to null-guard each lookup (check the result of GetValue
and ensure previousJob/newJob is not null before accessing ["plat"] or
["ducats"]), or better extract a small helper (e.g. TryGetMarketValues(string
key, out double plat, out int ducats) used by UpdateTotalsForOptionChange) to
centralize the GetValue, null-check, parsing (double.TryParse/int.TryParse) and
return success/failure so you avoid duplicated code and prevent NREs when a key
is missing.

---

Nitpick comments:
In `@WFInfo/AutoAddViewModel.cs`:
- Line 100: The public mutable field _parent on AutoAddViewModel breaks
encapsulation and uses an underscore prefix reserved for private backing fields;
change _parent to a private readonly field or expose it as a read-only property
(e.g., Parent) set via the AutoAddViewModel constructor (or at minimum mark it
internal instead of public) so external callers cannot mutate it directly and
the naming follows conventions; update any callers to use the new
constructor/property.
- Around line 134-149: Constructor AutoAddSingleItem sets ActiveOption before
assigning _parent which makes behavior ordering-dependent; move the assignment
_parent = parent to before setting ActiveOption inside AutoAddSingleItem (or
alternatively remove the redundant call to UpdateTotalsForOptionChange inside
addItem), so that ActiveOption's setter can safely call
_parent?.UpdateTotalsForOptionChange without relying on null ordering; update or
add a short comment on the constructor explaining the intended ordering if you
choose to keep the current sequence.

@D1firehail
Copy link
Contributor

I suggest letting each AutoAddSingleItem keep track of its own plat/ducat value, with updates triggering AutoAddViewModel to re-sum the items. That should solve the rounding issues of the incremental approach you're using now.

@occluder
Copy link
Author

occluder commented Feb 18, 2026

I have deliberately not implemented CodeRabbit's suggestions above as they require a higher language version. The code to get an item's value is copy pasted from another part of the codebase. Let me know if any changes are necessary

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 18, 2026

Caution

Failed to replace (edit) comment. This is likely due to insufficient permissions or the comment being deleted.

Error details
{"name":"HttpError","status":500,"request":{"method":"PATCH","url":"https://api.github.com/repos/WFCD/WFinfo/issues/comments/3914120901","headers":{"accept":"application/vnd.github.v3+json","user-agent":"octokit.js/0.0.0-development octokit-core.js/7.0.6 Node.js/24","authorization":"token [REDACTED]","content-type":"application/json; charset=utf-8"},"body":{"body":"<!-- This is an auto-generated comment: summarize by coderabbit.ai -->\n<!-- walkthrough_start -->\n\n<details>\n<summary>📝 Walkthrough</summary>\n\n## Walkthrough\n\nAdds aggregate TotalPlatinum (double) and TotalDucats (int) to AutoAddViewModel with automatic recalculation on collection/item changes and when an item's ActiveOption changes. AutoAddSingleItem now tracks parsed Platinum/Ducat values and updates the parent. UI (AutoCount.xaml) displays these totals and adjusts layout/bindings.\n\n## Changes\n\n|Cohort / File(s)|Summary|\n|---|---|\n|**ViewModel: totals & wiring** <br> `WFInfo/AutoAddViewModel.cs`|Added `TotalPlatinum` (double) and `TotalDucats` (int) with private setters and PropertyChanged notifications. Added backing fields, `RecalculateTotals()`, `ItemChanged` and `CollectionChanged` handlers, collection subscription/unsubscription, and destructor cleanup. Item add/remove now manage child event subscriptions and trigger recalculation.|\n|**Item: option/value propagation** <br> `WFInfo/AutoAddViewModel.cs` (class `AutoAddSingleItem`)|Added `_activeOption` field, `PlatinumValue` (double) and `DucatValue` (int) properties, numeric parsing style constant, `UpdateValues()` to parse/fetch market values with fallbacks, and ActiveOption setter logic to update values and notify parent. Preserves public parent reference for communication.|\n|**UI: totals display & bindings** <br> `WFInfo/AutoCount.xaml`|DataGrid SelectedItem binding now uses `UpdateSourceTrigger=PropertyChanged`. Bottom Grid changed from 2→3 columns. Replaced label with StackPanel showing \"Total:\", platinum icon and `TotalPlatinum`, ducat icon and `TotalDucats`. \"Save all\" moved to column 1, \"Dismiss all\" to column 2.|\n\n## Sequence Diagram\n\n```mermaid\nsequenceDiagram\n    participant UI as AutoCount UI\n    participant Item as AutoAddSingleItem\n    participant VM as AutoAddViewModel\n    participant Market as MarketData\n\n    UI->>Item: Change ActiveOption (user)\n    Item->>Item: set ActiveOption\\ncall UpdateValues()\n    Item->>Market: request platinum/ducat for option\n    Market-->>Item: return values (or null)\n    Item->>Item: parse values (NumberStyles)\n    Item->>VM: notify parent (PropertyChanged / direct call)\n    VM->>VM: ItemChanged -> RecalculateTotals()\n    VM->>VM: sum Platinum/Ducats across collection\n    VM->>UI: PropertyChanged TotalPlatinum / TotalDucats\n    UI->>UI: update totals display\n```\n\n## Estimated code review effort\n\n🎯 3 (Moderate) | ⏱️ ~20 minutes\n\n## Poem\n\n> 🐰 I rabbit-hop through code and sums,  \n> I count the platinum, clang the drums,  \n> When options flip and values sway,  \n> I nudge the totals—every day,  \n> Now UI gleams with numbers plumb! ✨\n\n</details>\n\n<!-- walkthrough_end -->\n\n\n<!-- pre_merge_checks_walkthrough_start -->\n\n<details>\n<summary>🚥 Pre-merge checks | ✅ 2 | ❌ 1</summary>\n\n### ❌ Failed checks (1 warning)\n\n|     Check name     | Status     | Explanation                                                                          | Resolution                                                                         |\n| :----------------: | :--------- | :----------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------- |\n| Docstring Coverage | ⚠️ Warning | Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. | Write docstrings for the functions missing them to satisfy the coverage threshold. |\n\n<details>\n<summary>✅ Passed checks (2 passed)</summary>\n\n|     Check name    | Status   | Explanation                                                                                                                     |\n| :---------------: | :------- | :------------------------------------------------------------------------------------------------------------------------------ |\n| Description Check | ✅ Passed | Check skipped - CodeRabbit’s high-level summary is enabled.                                                                     |\n|    Title check    | ✅ Passed | The title accurately describes the main feature added: displaying cumulative Platinum and Ducats totals in the Auto Add window. |\n\n</details>\n\n<sub>✏️ Tip: You can configure your own custom pre-merge checks in the settings.</sub>\n\n</details>\n\n<!-- pre_merge_checks_walkthrough_end -->\n\n<!-- finishing_touch_checkbox_start -->\n\n<details>\n<summary>✨ Finishing Touches</summary>\n\n- [ ] <!-- {\"checkboxId\": \"7962f53c-55bc-4827-bfbf-6a18da830691\"} --> 📝 Generate docstrings\n<details>\n<summary>🧪 Generate unit tests (beta)</summary>\n\n- [ ] <!-- {\"checkboxId\": \"f47ac10b-58cc-4372-a567-0e02b2c3d479\", \"radioGroupId\": \"utg-output-choice-group-unknown_comment_id\"} -->   Create PR with unit tests\n- [ ] <!-- {\"checkboxId\": \"07f1e7d6-8a8e-4e23-9900-8731c2c87f58\", \"radioGroupId\": \"utg-output-choice-group-unknown_comment_id\"} -->   Post copyable unit tests in a comment\n\n</details>\n\n</details>\n\n<!-- finishing_touch_checkbox_end -->\n\n<!-- tips_start -->\n\n---\n\nThanks for using [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=WFCD/WFinfo&utm_content=411)! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.\n\n<details>\n<summary>❤️ Share</summary>\n\n- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai)\n- [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai)\n- [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai)\n- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)\n\n</details>\n\n<sub>Comment `@coderabbitai help` to get the list of available commands and usage tips.</sub>\n\n<!-- tips_end -->\n\n<!-- internal state start -->\n\n\n<!-- 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 -->\n\n<!-- internal state end -->"},"request":{"retryCount":3,"retries":3,"retryAfter":16}}}

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
WFInfo/AutoAddViewModel.cs (1)

215-222: ⚠️ Potential issue | 🟡 Minor

RaisePropertyChanged() in RemoveFromParent fires for a non-existent property.

With no explicit argument, [CallerMemberName] injects "RemoveFromParent" as the property name. No property by that name exists, so all listeners receive a spurious change event. If the intent is to signal that the item was removed, the notification is better placed on an actual property; if there is no such intent, the call should be removed.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@WFInfo/AutoAddViewModel.cs` around lines 215 - 222, The
RaisePropertyChanged() call in RemoveFromParent fires a spurious notification
because CallerMemberName will emit "RemoveFromParent" which is not a real
property; fix by either removing the RaisePropertyChanged() call entirely from
RemoveFromParent if no property change should be announced, or replace it with a
call that supplies the actual property name that changed (e.g.,
RaisePropertyChanged("Parent") or the relevant property like "IsRemoved" or the
collection property that observers expect) and ensure that property (or an
appropriate boolean flag) exists on the class; locate the RemoveFromParent
method and the _parent.removeItem(this) call to apply the change.
🧹 Nitpick comments (2)
WFInfo/AutoAddViewModel.cs (2)

58-63: Redundant RecalculateTotals() call in removeItem.

_itemList.Remove(item) already fires CollectionChanged, which calls RecalculateTotals(). The explicit call on line 62 is redundant.

♻️ Proposed fix
         public void removeItem(AutoAddSingleItem item)
         {
             item.PropertyChanged -= ItemChanged;
             _itemList.Remove(item);
-            RecalculateTotals();
         }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@WFInfo/AutoAddViewModel.cs` around lines 58 - 63, In
removeItem(AutoAddSingleItem item) the explicit call to RecalculateTotals() is
redundant because _itemList.Remove(item) triggers the CollectionChanged handler
that already calls RecalculateTotals; remove the direct RecalculateTotals()
invocation (keep the PropertyChanged unsubscribe and the _itemList.Remove(item)
call intact) so totals are only recalculated via the collection change event.

27-44: Consider using SetField to avoid spurious property-change notifications.

Both TotalPlatinum and TotalDucats unconditionally call RaisePropertyChanged() even when the computed total is identical to the previous value. Since RecalculateTotals fires on every ItemChanged and every CollectionChanged, this can produce unnecessary UI re-renders. The SetField helper on the INPC base class already provides equality-gated notification.

♻️ Proposed refactor
-        public double TotalPlatinum
-        {
-            get => _totalPlatinum;
-            private set
-            {
-                _totalPlatinum = value;
-                RaisePropertyChanged();
-            }
-        }
-        public int TotalDucats
-        {
-            get => _totalDucats;
-            private set
-            {
-                _totalDucats = value;
-                RaisePropertyChanged();
-            }
-        }
+        public double TotalPlatinum
+        {
+            get => _totalPlatinum;
+            private set => SetField(ref _totalPlatinum, value);
+        }
+        public int TotalDucats
+        {
+            get => _totalDucats;
+            private set => SetField(ref _totalDucats, value);
+        }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@WFInfo/AutoAddViewModel.cs` around lines 27 - 44, The property setters for
TotalPlatinum and TotalDucats currently assign and call RaisePropertyChanged
unconditionally, causing spurious notifications when RecalculateTotals runs on
ItemChanged/CollectionChanged; change both setters to use the INPC base helper
SetField (or its equivalent) to perform equality-checked assignment and only
raise PropertyChanged when the value actually changes so UI rerenders are
avoided.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@WFInfo/AutoAddViewModel.cs`:
- Around line 84-87: Remove the finalizer ~AutoAddViewModel() that unsubscribes
_itemList.CollectionChanged because detaching managed events in a finalizer is
unsafe and unnecessary; either delete the finalizer entirely from the
AutoAddViewModel class, or if explicit teardown is required implement
IDisposable on AutoAddViewModel and move the _itemList.CollectionChanged -=
CollectionChanged logic into Dispose() (ensuring Dispose is idempotent and
called by consumers).
- Around line 148-150: The ternary in ActiveOption uses a dead null check on
options (new ObservableCollection<string>(options) already throws if options is
null); remove the redundant "options != null" and read the selected value from
the newly assigned RewardOptions collection instead. Concretely, keep the
activeIndex bounds logic, and set ActiveOption = activeIndex >= 0 ?
RewardOptions[activeIndex] : "" (referencing RewardOptions, ActiveOption,
activeIndex and the ObservableCollection<string>(options) construction).

---

Outside diff comments:
In `@WFInfo/AutoAddViewModel.cs`:
- Around line 215-222: The RaisePropertyChanged() call in RemoveFromParent fires
a spurious notification because CallerMemberName will emit "RemoveFromParent"
which is not a real property; fix by either removing the RaisePropertyChanged()
call entirely from RemoveFromParent if no property change should be announced,
or replace it with a call that supplies the actual property name that changed
(e.g., RaisePropertyChanged("Parent") or the relevant property like "IsRemoved"
or the collection property that observers expect) and ensure that property (or
an appropriate boolean flag) exists on the class; locate the RemoveFromParent
method and the _parent.removeItem(this) call to apply the change.

---

Duplicate comments:
In `@WFInfo/AutoAddViewModel.cs`:
- Around line 156-171: UpdateValues currently casts the result of
Main.dataBase.marketData.GetValue(ActiveOption) to JObject and then dereferences
job["plat"] which throws NullReferenceException when the key is missing; modify
UpdateValues to capture the result into a JToken/JObject variable from
Main.dataBase.marketData.GetValue(ActiveOption), check for null (or use
TryGetValue if available) before accessing job["plat"] and job["ducats"], and if
missing set PlatinumValue and DucatValue to 0 (or the existing else-path) so
missing marketData entries (e.g. "Forma Blueprint") no longer crash the UI.

---

Nitpick comments:
In `@WFInfo/AutoAddViewModel.cs`:
- Around line 58-63: In removeItem(AutoAddSingleItem item) the explicit call to
RecalculateTotals() is redundant because _itemList.Remove(item) triggers the
CollectionChanged handler that already calls RecalculateTotals; remove the
direct RecalculateTotals() invocation (keep the PropertyChanged unsubscribe and
the _itemList.Remove(item) call intact) so totals are only recalculated via the
collection change event.
- Around line 27-44: The property setters for TotalPlatinum and TotalDucats
currently assign and call RaisePropertyChanged unconditionally, causing spurious
notifications when RecalculateTotals runs on ItemChanged/CollectionChanged;
change both setters to use the INPC base helper SetField (or its equivalent) to
perform equality-checked assignment and only raise PropertyChanged when the
value actually changes so UI rerenders are avoided.

@occluder
Copy link
Author

occluder commented Mar 2, 2026

@D1firehail Any chance this could be looked at again? I'd like to have things ironed out before someone with merge capability takes a look

@D1firehail
Copy link
Contributor

Yeah no problem. Not sure I'll have time today, but should be able to within a few days at most.

{
public AutoAddViewModel _parent;

private const NumberStyles style = NumberStyles.AllowDecimalPoint | NumberStyles.AllowThousands | NumberStyles.AllowExponent;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The necessity of this confused me a bit, but apparently the overload of double.TryParse that accepts a CultureInfo without NumberStyles doesn't exist in our .NET version.

@D1firehail
Copy link
Contributor

LGTM

I could imagine similar info (and ducat efficiency) on a per-item level to be somewhat useful, but it's far from necessary and would require UI space considerations. No need to bother until/unless someone actually requests it.

@occluder
Copy link
Author

occluder commented Mar 3, 2026

Initially I had thoughts about having a plat/ducats per minute counter, but I have lost interest in that thought. If someone is interested in any of the mentioned ideas I would be happy to put in the effort

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants