<f{"id":235,"date":"2013-04-20T23:48:22","date_gmt":"2013-04-20T22:48:22","guid":{"rendered":"http:\/\/www.bernhard-krenz.de\/?p=235"},"modified":"2013-04-20T23:48:22","modified_gmt":"2013-04-20T22:48:22","slug":"falsche-bild-grosen-in-wpf","status":"publish","type":"post","link":"https:\/\/www.bernhard-krenz.de\/?p=235","title":{"rendered":"Falsche Bild-Gr\u00f6\u00dfen in WPF"},"content":{"rendered":"<p>Als WPF-Entwickler, der hin und wieder mit einem Designer zusammen arbeitet, wird man fr\u00fcher oder sp\u00e4ter mit dem Problem konfrontiert, dass die zugelieferten Grafiken in der Anwendung gr\u00f6\u00dfer dargestellt werden, als sie abgespeichert wurden.<\/p>\n<p>Dies wird immer dann auftreten, wenn ein Control die Gr\u00f6\u00dfe des darin enthaltenen Bildes annehmen soll, zum Beispiel ein Button.<\/p>\n<p>Ursache hierf\u00fcr ist ziemlich sicher, dass der Designer die Grafiken mit einem Apple-Mac erstellt hat. Dieser arbeitet standardm\u00e4\u00dfig mit 72dpi f\u00fcr die Grafiken, w\u00e4hrend Microsoft in Windows 96dpi verwendet. Wird das Bild in WPF dargestellt, wird es um den Faktor 96\/72 = 1,33 gr\u00f6\u00dfer dargestellt.<br \/>\nEine relativ schlechte L\u00f6sung w\u00e4re, die Bild-Gr\u00f6\u00dfen statisch im Code zu hinterlegen. Sp\u00e4tere Gr\u00f6\u00dfen\u00e4nderung des Bildes m\u00fcssten dann jedes Mal zus\u00e4tzlich auch im Code nachgearbeitet werden.<\/p>\n<p>Da ich in meinem Projekten recht h\u00e4ufig mit solchen Konstellationen arbeite, habe ich ein kleines UserControl entwickelt, dass sich diesem Problem annimmt. Beim \u00d6ffnen des Bildes wird die Orginalgr\u00f6\u00dfe ausgelesen und dem Bild zugewiesen. Der DPI-Wert wird ignoriert.<\/p>\n<p>Das UserControl arbeitet aktuell nur mit einem BitmapSource als Source des Bildes, zum Beispiel eine Pfad zu einem Bild.<\/p>\n<p>Folgend der Code f\u00fcr das Control:<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\npublic class DPIAwareImage : Image\r\n{\r\n\tstatic DPIAwareImage()\r\n\t{\r\n\t\t\/\/ listen to changes to stretch property, and set default value to fill\r\n\t\tStretchProperty.OverrideMetadata(typeof(DPIAwareImage), new FrameworkPropertyMetadata(Stretch.Fill, new PropertyChangedCallback(StretchPropertyChanged)));\r\n\t\t\/\/\/ listen to changes to source property\r\n\t\tSourceProperty.OverrideMetadata(typeof(DPIAwareImage), new FrameworkPropertyMetadata(new PropertyChangedCallback(SourcePropertyChanged)));\r\n\t}\r\n\r\n\t\/\/ check if a Stretch other then Fill is set.\r\n\tprivate static void StretchPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)\r\n\t{\r\n\t\tif (args.NewValue == null)\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tif ((Stretch)args.NewValue != Stretch.Fill)\r\n\t\t{\r\n\t\t\tthrow new NotSupportedException(&quot;DPIAwareImage only works with Stretch=Fill.&quot;);\r\n\t\t}\r\n\t}\r\n\r\n\t\/\/ check the new image source and set the origin width and height if available\r\n\tprivate static void SourcePropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)\r\n\t{\r\n\t\tvar source = args.NewValue as BitmapSource;\r\n\r\n\t\tif (source == null)\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tvar image = sender as DPIAwareImage;\r\n\r\n\t\timage.Stretch = Stretch.Fill;\r\n\t\timage.Width = source.PixelWidth;\r\n\t\timage.Height = source.PixelHeight;\r\n\t}\r\n}\r\n<\/pre>\n<p>In den Zeilen 38 und 39 wird die Orginalgr\u00f6\u00dfe der Datenquelle ausgelesen und dem Bild zugewiesen.<\/p>\n<p>Das Control \u00fcberwacht neben \u00c4nderungen der Source-Eigenschaft auch die Stretch-Eigenschaft. Alles au\u00dfer &#8222;Fill&#8220; w\u00fcrde f\u00fcr den Verwendungszweck nicht funktionieren, da sich der m\u00f6glicherweise &#8222;falsche&#8220; DPI-Inhalt an die festgelegte Gr\u00f6\u00dfe skalieren muss.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Als WPF-Entwickler, der hin und wieder mit einem Designer zusammen arbeitet, wird man fr\u00fcher oder sp\u00e4ter mit dem Problem konfrontiert,<a href=\"https:\/\/www.bernhard-krenz.de\/?p=235\" class=\"searchmore\">Weiterlesen&hellip;<\/a><\/p>\n<div class=\"clr\"><\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[14,6],"tags":[7,15],"_links":{"self":[{"href":"https:\/\/www.bernhard-krenz.de\/index.php?rest_route=\/wp\/v2\/posts\/235"}],"collection":[{"href":"https:\/\/www.bernhard-krenz.de\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.bernhard-krenz.de\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.bernhard-krenz.de\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.bernhard-krenz.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=235"}],"version-history":[{"count":11,"href":"https:\/\/www.bernhard-krenz.de\/index.php?rest_route=\/wp\/v2\/posts\/235\/revisions"}],"predecessor-version":[{"id":246,"href":"https:\/\/www.bernhard-krenz.de\/index.php?rest_route=\/wp\/v2\/posts\/235\/revisions\/246"}],"wp:attachment":[{"href":"https:\/\/www.bernhard-krenz.de\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=235"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.bernhard-krenz.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=235"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.bernhard-krenz.de\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=235"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}