<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Programming on Martin‘s Physics Club</title><link>https://martinphysics.club/categories/programming/</link><description>Recent content in Programming on Martin‘s Physics Club</description><generator>Hugo</generator><language>en-US</language><copyright>2020-2026 martinphysics.club</copyright><lastBuildDate>Fri, 25 Sep 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://martinphysics.club/categories/programming/index.xml" rel="self" type="application/rss+xml"/><item><title>I Built a Simple Optical Simulation Tool</title><link>https://martinphysics.club/posts/wp-100028/</link><pubDate>Fri, 28 Aug 2026 03:39:45 +0000</pubDate><guid>https://martinphysics.club/posts/wp-100028/</guid><description>&lt;p&gt;LightDraw began with a simple goal: make optics easier to teach, explore, and understand. I built this lightweight 2D simulator around real classroom needs, then extended it to visualize electrostatic and magnetostatic fields alongside optics.&lt;/p&gt;
&lt;p&gt;Built with .NET, Avalonia, and SkiaSharp, LightDraw makes abstract physics easier to see and explore.&lt;/p&gt;
&lt;h2 id="try-lightdraw"&gt;Try LightDraw&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Best experience:&lt;/strong&gt; Download the desktop client from the &lt;a href="https://apps.microsoft.com/detail/9P9JGS0LB77D?hl=en-us&amp;amp;gl=US"&gt;Microsoft Store&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Quick preview:&lt;/strong&gt; &lt;a href="https://lightdraw.martinphysics.club/"&gt;Run LightDraw in your browser&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Source code:&lt;/strong&gt; Explore &lt;a href="https://github.com/MatinxHT/LightDraw"&gt;LightDraw on GitHub&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;About the online version:&lt;/strong&gt; It runs in Avalonia&amp;rsquo;s WebAssembly (WASM) mode, where performance is significantly limited. Please use it for an initial evaluation or when you urgently need access. For regular use and the best experience, choose the desktop client.&lt;/p&gt;</description></item><item><title>I choose WPF as my first Windows-based App Framework in 2025</title><link>https://martinphysics.club/posts/wp-100003/</link><pubDate>Thu, 20 Mar 2025 14:04:23 +0000</pubDate><guid>https://martinphysics.club/posts/wp-100003/</guid><description>&lt;p&gt;&lt;strong&gt;Windows Presentation Foundation&lt;/strong&gt; (&lt;strong&gt;WPF&lt;/strong&gt;) was born in November 21, 2006. At that time i was a &amp;ldquo;child&amp;rdquo; who only know use VB.NET to creat old fashion GUI Application. At that time I prefer find a app than creat one by my-996-self.Not crazy about coding.&lt;/p&gt;
&lt;h4 id="the-beginning"&gt;The Beginning&lt;/h4&gt;
&lt;p&gt;The meaningful time is about 2016.Microsoft released &lt;strong&gt;Universal Windows Platform&lt;/strong&gt;(&lt;strong&gt;UWP&lt;/strong&gt;) Framework,coder can code one sample to publish in Windows 10 destop/Windows 10 mobile/XBoxOne. I was so attracted to learn &lt;strong&gt;UWP&lt;/strong&gt; by Channel 9&amp;rsquo;s video.I learned how to use XAML to design an interface/space and studied .NET syntax. From compiling a simple calculator to run on my Windows 10 PC and my Lumia phone, to flashing Windows 10 IoT on a Raspberry Pi and running my self-built local network media server—those were wonderful times.Back then, in China, platforms like NetEase Cloud Music were among the first to support the &lt;strong&gt;UWP&lt;/strong&gt; framework, bringing countless surprises to users. Unfortunately, we, the 1%, still lost in market.&lt;/p&gt;</description></item><item><title>Troubleshooting Property Update Issues in WPF DataGridCheckBoxColumn Bindings</title><link>https://martinphysics.club/posts/wp-100004/</link><pubDate>Tue, 03 Sep 2024 10:46:36 +0000</pubDate><guid>https://martinphysics.club/posts/wp-100004/</guid><description>&lt;p&gt;Why does the CheckBox state change in WPF &lt;code&gt;DataGridCheckBoxColumn&lt;/code&gt; not automatically update the bound property?&lt;/p&gt;
&lt;h2 id="situation"&gt;&lt;strong&gt;Situation：&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;My code has correctly implemented the binding relationship using the MVVM library, but I am unable to filter data using the checkbox in the DataGrid.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;//model&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SpectralPeakDataItem&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;IsUserFor&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;Wavelength&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;PixelPosition&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;InstensityPercentage&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;//ViewModel&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;[ObservableProperty]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="n"&gt;ObservableCollection&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;SpectralPeakDataItem&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_mercuryArgonSpectralPeakDataItems&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-xml" data-lang="xml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;ui:DataGrid&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;Grid.Column=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;0&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;Margin=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;5&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;AutoGenerateColumns=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;False&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;ItemsSource=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;{Binding MercuryArgonSpectralPeakDataItems, Mode=TwoWay}&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;DataGrid.Columns&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;DataGridCheckBoxColumn&lt;/span&gt; &lt;span class="na"&gt;Binding=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;{Binding IsUserFor, Mode=TwoWay}&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;Header=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;IsUserFor&amp;#34;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;DataGridTextColumn&lt;/span&gt; &lt;span class="na"&gt;Binding=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;{Binding Wavelength, Mode=TwoWay}&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;Header=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Wavelength&amp;#34;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;DataGridTextColumn&lt;/span&gt; &lt;span class="na"&gt;Binding=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;{Binding PixelPosition, Mode=TwoWay}&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;Header=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;PixelPosition&amp;#34;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;DataGridTextColumn&lt;/span&gt; &lt;span class="na"&gt;Binding=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;{Binding InstensityPercentage, Mode=TwoWay}&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;Header=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Percentage&amp;#34;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;/DataGrid.Columns&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;/ui:DataGrid&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;However, in the usual event-driven code design, it works fine.So, I think this is an issue with MVVM&amp;rsquo;s data binding, as it doesn&amp;rsquo;t seem to achieve data synchronization.So next, I discovered that:In a WPF &lt;code&gt;DataGridCheckBoxColumn&lt;/code&gt;, the reason why changes in the CheckBox&amp;rsquo;s checked state do not automatically trigger property updates is primarily because the &lt;code&gt;DataGridCheckBoxColumn&lt;/code&gt; uses a binding context that may not directly reflect changes in the CheckBox state. This often involves the following issues:&lt;/p&gt;</description></item><item><title>使用.Net搭配EF Core记录你城市的天气</title><link>https://martinphysics.club/posts/wp-100008/</link><pubDate>Fri, 08 Dec 2023 21:09:08 +0000</pubDate><guid>https://martinphysics.club/posts/wp-100008/</guid><description>&lt;h2 id="项目简述"&gt;项目简述&lt;/h2&gt;
&lt;p&gt;这个项目是我在学习.Net Core编程的时候用到的简单例子，整体就是通过Get请求获取某地区的天气信息，经过json反向序列化后写入到数据库中存储起来。通过.net6的EntityFramework我们可以很优雅地为这个小项目进行CodeFirst的设计（沿用杨中科老师的一个观点：“关系型数据库对程序员来讲只是一个存放数据模型的媒介，理想状态下程序员不用关心数据库的操作。”）这个项目将会用EntityFramework进行数据库的CURD操作，任务目标：&lt;/p&gt;</description></item></channel></rss>