It's pretty simple - WPF tells you that the display of data should not affect the code, just write the code, convert the data, and the display will work itself. Those. No need to think about how the string will be displayed - it will be a textbox, a textblock, a label, a loaf, whatever - just create a string. Of course, besides primitive types, there are more complex cases, but even here WPF says that you don’t need to be tied up with controls, write classes that support a couple of interfaces - it will be cheap and simple to add a class to such a class without changing the code.
It is worth noting that WPF is basically the Enterprise sector, i.e. healthy and long-lived applications. The cost of changes in them should be minimal and the probability of introducing bugs simply by changing the color \ frame \ distance is generally zero. Therefore, WPF is quite fundamentally different from WinForm - no static dimensions of controls, no attachments to numbers - everything is adaptive, a lot of problems such as styles / triggers, so that the behavior does not need to be programmed manually.
Of course, there are some downsides. When the application is a couple of thousand lines of code, it becomes quite difficult to find the cause of the visual bug, because there are about 10 different data sources for any WPF control property. Therefore, various frameworks appear, on the one hand, simplifying the creation of uniform views, on the other hand, implicitly imposing restrictions on the use of WPF buns in order not to create hell.
And now, by what you describe. dotNet uses links for classes, which means in the simplest case a class read from the database contains N fields of primitive types. As a result, the class either directly or through the wrapper goes to the WPF controls, taking up exactly the same amount of memory, for where you just need to put a reference to the instance, and not create a new one. In the case of a string, it is either displayed directly, i.e. There is one instance at all, or one duplicate is created at the view mode level in which MVVM is responsible for displaying / changing data.
It is worth noting that string data is cheap. If you are certainly not trying to display "War and Peace." If you climb inside WPF, then the display will be redundant, because for every user of the user there are quite a few MBs. If you do not have display problems right now (lagging animation, loss of controls, blinking) and memory (OutOfMemory, clogging of a swap) - it's easier not to think about it. And when they appear, everyone will have to take a profiler in their hands and look for the cause of the leak, and not to wonder if I have lost a couple of extra bytes in the bindings.