www.devexpress.com
Open in
urlscan Pro
2606:4700:10::6816:59e
Public Scan
Submitted URL: https://www.devexpress.com/go/v241_Get_WhatsNew.aspx
Effective URL: https://www.devexpress.com/subscriptions/whats-new/
Submission: On June 20 via manual from DE — Scanned from DE
Effective URL: https://www.devexpress.com/subscriptions/whats-new/
Submission: On June 20 via manual from DE — Scanned from DE
Form analysis
1 forms found in the DOMName: aspnetForm — POST ./
<form name="aspnetForm" method="post" action="./" id="aspnetForm">
<div>
<input type="hidden" name="__VSTATE" id="__VSTATE"
value="AW94qHzJzziLLz7AQzGAXIxYSqUXEdlgtQRAbKaVub+ENhz6+9zfG6woEM4PB2weZ3+0bSpPo7zQZ5YpQLd7WCfp7z84Dj75CiXwuEoS2324spIHvuTP/hNdEl7399vULMWdjWS/Y1JMPWZ8boee5XuFA84R3ufJNNiFpeZPZWbDdTMrxrrx8pRpjB93z8f6dMxEdPxOtmQ0FPLZg9/ukWPY3VwgbYlSQJEATqRlR9xu8HDgKfF7ubvbXQprP6qWaK1rJ+Kk9Q7ACV6/eAt2BJvluj8ddktDfPokLXo6sCizvWaAUbpqYdQsguZi9I0x1Pns1jHp9uM2S9PkPtIcVMTQAv1OvmhXG/KFvtIFP/ygXXPM4W9rnFlxYnNeXztK2RnDVz1JFJyolhPbQ0mWZl/pcU04LgaPI3Q4PzqBOWdV8Kb46W2VaN+B6QuxMaWBcE/Y5WPu2V/NFY8RWV85TOWOSJtLmcOC6Py3p/3eM55cvwRWkxE46US8yLIT8GeIH1kknCH6oyZJddvNlb36N40wHbdGC1HnUjAS3+jKco98BneujXlIU/kdRK2Ljg+Jpj3NmF113G1T9k+Swq6lmIC6HawIIIzqx3zG80v/gpmhEUOhiINlilxmSWXRDq43H35+YDp1mOizBDyX4qF/AZSA+OzepF7iqbejVP9rfIX0GZOpfn2f+a2kCVWhLhUwmiqQOe6ohmqIzDXoutgcDy2kVTb/p0RlK2UCfr705jefTPZ8/yLZ2manFX7NbiMGgHs9Ei/oIuTdgfVQN5LrSL4LKpquqSjmPsRWonRo2CEJfWp+otOE/+am5WY2xOfjot+nqD7F5UqB5PVMJzCX76RI2taHjcDA0AMFzONWUSwSxTJnOZXv6RKkU3bTdCmLlrJpPdhWr7G4ypBe1FUJmsLDufNNk1sQHI0wpBM/WRbV8ao0WFuBkXdXtQwvGh48ffn7NJgdnkry3VXhmh4OD2mL4/aJxG+dpt0x9FBF0S2SCU1oaRrZTalN2/LTQOdiJWEr8kD2VDo9uzoLWaemRwjIYoPhI9AQiR+VveTyWcYSdMQ1gDpamhly7+ECYDE7MdbRXptsN4a8uWgztNRXjMyRv05E0DXbHPKNSwaz0w8ErN2lb6yFepH8TZZL+8qwQZeyyJ7Cr7QxT4NRX3Q0WaYVKZhNQA/cJXpo8G6OMgWNPBaT4DcQ3WEkhbNlJa3uWvS9cpbh7Oeuu1GDOF2Wl2D83BzLuMvx3OB+ELv/IC0bU0rNyliJNxgC7tofC3rlqVAKgU0uN7gu2y9MF98bUDkS8O+IJDG05juDQzHVtUddPmpVWIum1FaJycDOoj9ZJA6q8lj8SAvvmwucIKOLugrUkwMlDultYUxx3WUR6MChIZ8GLGtU84ZYwEkZqxT4dgiEy1sJZ//jbxXvvj5Y5NhPv/o+ktsbvUeXb3oLQHMqIgodVLs2iuUlMG2sl3Wvnl+rv4o/dNGL/vUErQQ55F/ZKQ6md8Jk5VORnd1VprYmeGBHhh6U1PeBvqEWlCo+/C52z3qJNF9cJj3nbEL2z52noJu3QeOm9EJkmS/So3KFaqCOZ09oxIkzIgTo3GO0F/xttIbDvNo4fVEHrIemD8jL9tSR6P9irSlRjpryjtshYUcwBfh3M3mrz5X3zLO0hBZpVdXTNbKgMzMfj+a/P4yS90+qWh3vfsleixqRarDdKea/qwaecrjzYmtbzDGQTdpxzQW74m++Qc7EX2FoI2UNGTNDWW+LyuQWPLrWtbeEjHVLMHG8/BbspTO3QjqQ7oqr671oCcdX/wABhMSMOrWCi2sBzn2fhLMaIQCTBbwUmwYTcyes4YSOcs6U+ZF0KDQm8SG0yJvuX+zUckuFV6ejMYOoEBMqb4AQnaIXoBbivWMW6lhnWAFFfxYET0rIexxVROiY7emFhS4FUjORBpQCtgeBraHmvfOZBbMSDH8IZZga/ZsPKZGtGvowkMz1Wd606Vocau20rKD8gD+mIf2vpJI6XTH9PfcsM5JwwjUmYnsQ">
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="">
</div>
<div>
<input type="hidden" name="__EVENTVALIDATION" id="__EVENTVALIDATION" value="/wEdAAKvVXD1oYELeveMr0vHCmYPbmOiP4Z8AWX9VyP6/jUv12tJ2V89qhNSttAEumhlHzO6mYaN">
</div>
<script type="text/javascript">
var _wsData = {
"Settings": {
"MainWebSiteUrl": "https:\/\/www.devexpress.com\/",
"TrackingEnabled": true
},
"UserInfo": {
"IsLoggedIn": false
}
};
</script>
<header class="Fixed">
<div id="TOCChatLink"> Chat Now </div>
<div class="r-container">
<a tabindex="-1" class="Logo" title="DevExpress" href="https://www.devexpress.com/" id="Header-Logo"></a>
<div class="ControlContainer">
<a id="Cart" tabindex="-1" title="Shopping Cart" data-empty-text="Cart" data-cart-text="Cart: ##" href="https://www.devexpress.com/ClientCenter/Purchase/Checkout/">Cart</a><a id="MyDownloads" tabindex="-1" class="HeadLink hidden visible-xs" href="https://www.devexpress.com/ClientCenter/DownloadManager/">My Downloads</a><a id="FreeTrial" tabindex="-1" class="HeadLink Button Orange hidden visible-xs" href="https://www.devexpress.com/Products/Try/">Free Trial</a><a id="LogIn" tabindex="-1" class="HeadLink" href="https://www.devexpress.com/MyAccount/LogIn/?returnUrl=https%3A%2F%2Fwww.devexpress.com%2Fsubscriptions%2Fwhats-new%2F">Log In</a>
<div id="MyAccount"
data-myaccount="{"Urls":{"Login":"https://www.devexpress.com/MyAccount/LogIn/?returnUrl=https%3a%2f%2fwww.devexpress.com%2fsubscriptions%2fwhats-new%2f","ManageProfile":"https://www.devexpress.com/MyAccount/","Download":"https://www.devexpress.com/ClientCenter/DownloadManager/","Renew":"https://www.devexpress.com/Buy/Renew/","PurchaseHistory":"https://www.devexpress.com/ClientCenter/PurchaseHistory.aspx","ManageLicenses":"https://www.devexpress.com/ClientCenter/LicenseManager/","Logout":"https://www.devexpress.com/MyAccount/LogOut/?returnUrl=https%3a%2f%2fwww.devexpress.com%2fsubscriptions%2fwhats-new%2f"}}"
style="display:none;">
<span class="UserIcon"></span>
</div>
<div id="SiteSearch">
<div title="Search" class="SearchButton">
</div>
<div class="SearchBox">
<input name="ctl00$ctl00$tbSiteSearch" type="text" value="Type keywords here" id="tbSiteSearch" tabindex="-1" class="NullText" autocomplete="off" nulltext="Type keywords here">
</div>
</div>
<div id="NotificationCenter" tabindex="-1">
<a tabindex="-1" data-notifications-control="bell" href="javascript:;"><span class="Bell"></span><span class="MessageCount" data-notifications-count="0"></span></a>
<div class="UnreadHint" style="left: -87px;">
<div class="Hint" data-notifications-count="0"></div>
</div>
<div class="NotificationsList" style="left: -204px; width: 430px;"></div>
</div>
</div>
</div>
</header>
<div class="HeaderPlaceholer" style="height: 36px;"></div>
<script type="text/javascript">
window.SearchServiceUrl = 'https://search.devexpress.com/?m=Web&q=';
</script>
<nav id="MainMenu">
<div class="MenuContainer">
<div class="r-container">
<a tabindex="-1" class="Logo" title="DevExpress" href="https://www.devexpress.com/" id="TOC-Logo"></a><a tabindex="-1" class="Menu-Toggle" href="javascript:;" data-role="Menu-Toggle-Button"><span></span></a>
<div class="h-clear hidden-md">
</div>
<ul>
<li><a tabindex="-1" href="javascript:;">Products</a>
<div class="SubMenu Products">
<div class="Header hidden-md">
<span>Products</span>
<div class="CloseButton">
</div>
</div>
<div class="r-container">
<div class="ScrollContainer">
<div class="column">
<div class="GroupTitle"> MULTI-PLATFORM PACKAGES </div>
<a tabindex="-1" href="https://www.devexpress.com/subscriptions/universal.xml"><svg data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 72" width="72px" height="72px"><title xmlns=""></title><path style="fill:#ff7200;" d="M5.4,72H66.6A5.42,5.42,0,0,0,72,66.6V5.4A5.42,5.42,0,0,0,66.6,0H5.4A5.42,5.42,0,0,0,0,5.4V66.6A5.42,5.42,0,0,0,5.4,72Z"></path><path style="fill: #fff" d="M35.94,50.77q3.69,0,5.49-2,1.5-1.74,1.5-6.66V20.24H39v21.9A8.42,8.42,0,0,1,38.36,46,2.51,2.51,0,0,1,36,47a2.49,2.49,0,0,1-2.38-1.07,10.46,10.46,0,0,1-.59-4.34V20.24h-4V41.55c0,3.3.38,5.52,1.15,6.68C31.33,49.92,33.23,50.77,35.94,50.77Z"></path></svg>Universal Subscription</a><abbr>Our
Best Value – includes over 600 UI Controls, our award-winning reporting platform, DevExpress Dashboard, the eXpressApp Framework, CodeRush for Visual Studio and
more.</abbr><a tabindex="-1" href="https://www.devexpress.com/subscriptions/dxperience.xml"><svg data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 72" width="72px" height="72px"><title xmlns=""></title><path style="fill:#26a4dd" d="M5.4,72H66.6A5.42,5.42,0,0,0,72,66.6V5.4A5.42,5.42,0,0,0,66.6,0H5.4A5.42,5.42,0,0,0,0,5.4V66.6A5.42,5.42,0,0,0,5.4,72Z"></path><path style="fill:#fff" d="M25.05,48.43a8.93,8.93,0,0,0,2.58-4.59,34.12,34.12,0,0,0,.8-8.13,36.83,36.83,0,0,0-.72-8.34,11,11,0,0,0-2.42-4.88,6.23,6.23,0,0,0-2.58-1.74,12.55,12.55,0,0,0-3.85-.51h-5V50.4h3.28Q22.84,50.4,25.05,48.43ZM17.92,23.66h.51a4.53,4.53,0,0,1,4.51,2.62q1.23,2.61,1.23,9.59,0,6.48-1.29,8.73t-5,2.25Z"></path><path style="fill:#fff" d="M33.8,50.4l1.74-5.47.35-1.13.69-2.15a14.2,14.2,0,0,0,.52-2.5,22.18,22.18,0,0,0,.53,2.42c.25.91.57,1.94,1,3.09l2,5.74h4.1L39.12,35.09,44.7,20.24H40.6l-1.93,6.21-.28.88c-.19.63-.38,1.25-.55,1.88s-.34,1.27-.48,1.93a31,31,0,0,0-1.47-5.06L33.8,20.24H29.86l5.35,14.85L29.51,50.4Z"></path><path style="fill:#fff" d="M51,37a13,13,0,0,0,5.14-.8q3.52-1.76,3.53-7.77c0-2.85-.58-4.94-1.76-6.25s-3-2-5.62-2H46.93V50.4H51Zm0-13.36h.57a3.46,3.46,0,0,1,2.95,1.25,6.68,6.68,0,0,1,.93,3.95,5.37,5.37,0,0,1-1,3.67c-.64.68-1.8,1-3.48,1Z"></path></svg>DXperience Subscription</a><abbr>Save
Hundreds – includes DevExpress UI Controls for WinForms, ASP.NET, MVC, WPF, our award-winning reporting platform and CodeRush for Visual Studio.</abbr>
<div class="h-clear">
</div>
</div>
<div class="column">
<div class="column">
<div class="GroupTitle"> WINDOWS DESKTOP CONTROLS </div>
<a tabindex="-1" href="https://www.devexpress.com/products/net/controls/winforms/"><svg data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 72" width="72px" height="72px"><title xmlns=""></title><path style="fill:#26a4dd" d="M66.6,0H5.4A5.42,5.42,0,0,0,0,5.4V66.6A5.42,5.42,0,0,0,5.4,72H66.6A5.42,5.42,0,0,0,72,66.6V5.4A5.42,5.42,0,0,0,66.6,0Z"></path><path style="fill:#fff" d="M55.16,31.49c0,1.67.08,3.45.23,5.34s.4,4,.73,6.32A111.37,111.37,0,0,0,53,32.27l-4-12H45.18V50.4h4L49,37.26c0-.38,0-.72,0-1s0-.55,0-.76l-.24-3.73-.21-3.07c0-.17,0-.37-.06-.61s-.06-.53-.1-.87c.08.34.15.63.21.9s.1.48.13.66c.31,1.46.65,2.85,1,4.18s.76,2.62,1.18,3.89L55.42,50.4h3.8V20.24H55.16Z"></path><path style="fill:#fff" d="M28.46,32l-.29,2c-.18,1.38-.36,2.79-.52,4.22s-.31,2.92-.44,4.45c-.13-1.45-.3-3-.5-4.59s-.45-3.34-.75-5.21l-2-12.68H20.8L18.64,33.29c-.21,1.21-.4,2.53-.58,4s-.34,3-.5,4.7l-.1,1c0-.26,0-.48-.05-.65s0-.28,0-.35l-.22-2.56c-.08-.92-.19-1.94-.35-3.06l-.33-2.07-2-14H10.49L15.71,50.4H19l2.21-13c0-.09.06-.32.11-.7s.13-.9.22-1.56l.41-2.89q0-.16.09-.87c0-.48.1-1.15.16-2,0-.15,0-.33.06-.55s.05-.48.08-.78l.1,1.25c.06.71.12,1.31.18,1.77s.1.82.13,1.06l.41,3c.1.7.18,1.24.23,1.62s.09.59.1.64l2.13,13h3.16l5.34-30.16H30.2Z"></path><rect style="fill:#fff" x="36.47" y="20.24" width="4.06" height="30.16"></rect></svg>WinForms</a><a tabindex="-1" href="https://www.devexpress.com/products/net/controls/wpf/"><svg data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 72" width="72px" height="72px"><title xmlns=""></title><path style="fill:#26a4dd" d="M5.4,72H66.6A5.42,5.42,0,0,0,72,66.6V5.4A5.42,5.42,0,0,0,66.6,0H5.4A5.42,5.42,0,0,0,0,5.4V66.6A5.42,5.42,0,0,0,5.4,72Z"></path><path style="fill:#fff" d="M17.76,50.4l2.2-13a5.21,5.21,0,0,0,.12-.7c.05-.38.13-.9.22-1.56l.41-2.89c0-.11,0-.4.08-.87s.11-1.15.17-2c0-.15,0-.33.06-.55s.05-.48.08-.78l.1,1.25c.06.71.12,1.31.18,1.77s.1.82.13,1.06l.41,3c.1.7.18,1.24.23,1.62s.09.59.1.64l2.13,13h3.16l5.34-30.16H29L27.25,32l-.29,2c-.19,1.38-.36,2.79-.52,4.22s-.31,2.92-.44,4.45c-.13-1.45-.3-3-.5-4.59s-.45-3.34-.75-5.21l-2-12.68H19.59L17.43,33.29c-.21,1.21-.4,2.53-.58,4s-.34,3-.5,4.7l-.1,1c0-.26,0-.48-.05-.65s0-.28,0-.35l-.22-2.56c-.08-.92-.19-1.94-.35-3.06l-.33-2.07-2-14H9.28L14.5,50.4Z"></path><path style="fill:#fff" d="M39.32,37a13,13,0,0,0,5.14-.8Q48,34.46,48,28.45c0-2.85-.58-4.94-1.76-6.25s-3-2-5.62-2H35.26V50.4h4.06Zm0-13.36h.57a3.46,3.46,0,0,1,3,1.25,6.68,6.68,0,0,1,.93,3.95,5.37,5.37,0,0,1-1,3.67c-.64.68-1.8,1-3.48,1Z"></path><polygon style="fill:#fff" points="55.18 36.65 61.31 36.65 61.31 33.21 55.18 33.21 55.18 23.68 61.98 23.68 61.98 20.24 51.12 20.24 51.12 50.4 55.18 50.4 55.18 36.65"></polygon></svg>WPF</a><a tabindex="-1" href="https://www.devexpress.com/products/vcl/"><svg data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 72" width="72px" height="72px"><title xmlns=""></title><path style="fill:#26a4dd" d="M5.4,72H66.6A5.42,5.42,0,0,0,72,66.6V5.4A5.42,5.42,0,0,0,66.6,0H5.4A5.42,5.42,0,0,0,0,5.4V66.6A5.42,5.42,0,0,0,5.4,72Z"></path><path style="fill:#fff" d="M23.38,50.4,29.3,20.24H25.51l-2,11.14c0,.27-.11.58-.17.93s-.12.74-.18,1.16l-.69,4.59L22,41.55a5.67,5.67,0,0,0-.08.59c0,.23-.06.5-.1.8l-.2-1.48c-.06-.5-.14-1.05-.22-1.67s-.18-1.28-.28-2l-.65-4.37-.31-2L18.34,20.24h-4L20.16,50.4Z"></path><path style="fill:#fff" d="M40,50.77A6.58,6.58,0,0,0,43.25,50V46.22a6.11,6.11,0,0,1-2.41.63q-5.72,0-5.72-11.18a39.79,39.79,0,0,1,.32-5.38,14.14,14.14,0,0,1,1-3.76,5.13,5.13,0,0,1,1.71-2.19,4.22,4.22,0,0,1,2.48-.72,6.45,6.45,0,0,1,2.62.76V20.73a7,7,0,0,0-3.36-.9,7.36,7.36,0,0,0-6.85,4q-2.23,3.95-2.24,12Q30.8,50.77,40,50.77Z"></path><polygon style="fill:#fff" points="57.37 46.96 50.73 46.96 50.73 20.24 46.66 20.24 46.66 50.4 57.37 50.4 57.37 46.96"></polygon></svg>VCL</a><a tabindex="-1" href="https://www.devexpress.com/subscriptions/reporting/"><svg data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 72" width="72px" height="72px"><title xmlns=""></title><path style="fill:#26a4dd" d="M5.4,72H66.6A5.42,5.42,0,0,0,72,66.6V5.4A5.42,5.42,0,0,0,66.6,0H5.4A5.42,5.42,0,0,0,0,5.4V66.6A5.42,5.42,0,0,0,5.4,72Z"></path><polygon style="fill:#fff" points="45 16 45 24 53 24 45 16"></polygon><path style="fill:#fff" d="M36,39c5.52,0,10-1.79,10-4H35l3.83-3.83A23.15,23.15,0,0,0,36,31c-5.52,0-10,1.79-10,4S30.48,39,36,39Z"></path><path style="fill:#fff" d="M20,56H52a1,1,0,0,0,1-1V52H48V48l2,2h3L67,36l-5-5-9,9V25H44V16H20a1,1,0,0,0-1,1V55A1,1,0,0,0,20,56ZM63,36l1,1L53,48l-1-1Zm-2-2,1,1L51,46l-1-1ZM25,35c0-2.76,4.92-5,11-5s11,2.24,11,5v6c0,2.76-4.92,5-11,5s-11-2.24-11-5Z"></path></svg>Desktop Reporting</a>
<div class="h-clear">
</div>
<div class="GroupTitle"> ENTERPRISE & SERVER TOOLS </div>
<a tabindex="-1" href="https://www.devexpress.com/products/net/dashboard/"><svg data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 72" width="72px" height="72px"><title xmlns=""></title><path style="fill:#26a4dd" d="M5.4,72H66.6A5.42,5.42,0,0,0,72,66.6V5.4A5.42,5.42,0,0,0,66.6,0H5.4A5.42,5.42,0,0,0,0,5.4V66.6A5.42,5.42,0,0,0,5.4,72Z"></path><path style="fill:#fff" d="M64,32a19.91,19.91,0,0,0-6.38-14.62L43,32Z"></path><path style="fill:#fff" d="M40,47a14.94,14.94,0,0,1-1.72,7c.24,0,.48,0,.72,0A20,20,0,0,0,59,34H38L52.62,19.38A20,20,0,0,0,19,33.24,15,15,0,0,1,40,47Z"></path><path style="fill:#fff" d="M25,60A13,13,0,1,0,12,47,13,13,0,0,0,25,60Zm0-22a9,9,0,0,1,8.48,12H27l3-8-7,8H16.52A9,9,0,0,1,25,38Z"></path></svg>Business Intelligence Dashboard</a><a tabindex="-1" href="https://www.devexpress.com/products/net/report-server/"><svg data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 72" width="72px" height="72px"><title xmlns=""></title><path style="fill:#26a4dd" d="M66.6,0H5.4A5.42,5.42,0,0,0,0,5.4V66.6A5.42,5.42,0,0,0,5.4,72H66.6A5.42,5.42,0,0,0,72,66.6V5.4A5.42,5.42,0,0,0,66.6,0Z"></path><path style="fill:#fff" d="M41,18H18a1,1,0,0,0-1,1V57a1,1,0,0,0,1,1H50a1,1,0,0,0,1-1V28H41Zm4,19v6c0,2.76-4.92,5-11,5s-11-2.24-11-5V37c0-2.76,4.92-5,11-5S45,34.24,45,37Z"></path><path style="fill:#fff" d="M52,16H20a1,1,0,0,0-1,1H42L52,27V56a1,1,0,0,0,1-1V17A1,1,0,0,0,52,16Z"></path><path style="fill:#fff" d="M54,14H22a1,1,0,0,0-1,1H53a1,1,0,0,1,1,1V54a1,1,0,0,0,1-1V15A1,1,0,0,0,54,14Z"></path><path style="fill:#fff" d="M34,33c-5.52,0-10,1.79-10,4s4.48,4,10,4,10-1.79,10-4H33l3.83-3.83A23.15,23.15,0,0,0,34,33Z"></path></svg>Report & Dashboard Server</a><a tabindex="-1" href="https://www.devexpress.com/products/net/office-file-api/"><svg data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 72" width="72px" height="72px"><title xmlns=""></title><path style="fill:#26a4dd" d="M5.4,72H66.6A5.42,5.42,0,0,0,72,66.6V5.4A5.42,5.42,0,0,0,66.6,0H5.4A5.42,5.42,0,0,0,0,5.4V66.6A5.42,5.42,0,0,0,5.4,72Z"></path><path style="fill:#fff" d="M18,58H50a1,1,0,0,0,1-1V28H41V18H18a1,1,0,0,0-1,1V57A1,1,0,0,0,18,58Zm7-24H43v1H25Zm0,2H43v1H25Zm0,2H43v1H25Zm0,2H43v1H25Zm0,2H43v1H25Z"></path><path style="fill:#fff" d="M54,16V54a1,1,0,0,0,1-1V15a1,1,0,0,0-1-1H22a1,1,0,0,0-1,1H53A1,1,0,0,1,54,16Z"></path><path style="fill:#fff" d="M52,27V56a1,1,0,0,0,1-1V17a1,1,0,0,0-1-1H20a1,1,0,0,0-1,1H42Z"></path></svg>Office File API (XLS, DOC, PDF)</a>
<div class="h-clear">
</div>
<div class="GroupTitle"> MOBILE CONTROLS </div>
<a tabindex="-1" href="https://www.devexpress.com/maui/"><svg data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 72" width="72px" height="72px"><title xmlns=""></title><path style="fill:#26a4dd" d="M66.6,0H5.4A5.42,5.42,0,0,0,0,5.4V66.6A5.42,5.42,0,0,0,5.4,72H66.6A5.42,5.42,0,0,0,72,66.6V5.4A5.42,5.42,0,0,0,66.6,0Z"></path><path style="fill:#fff" d="M19.67,20.24c-1.15,6-3.21,15.79-4,21.7-.69-6-3-15.69-4.26-21.7H8L5.5,50.29H9.31l1.17-20.7c.63,5.89,2.75,14.84,3.93,20.7h2.73c1-5.13,3.12-15.64,3.83-20.7.15,6,.63,14.65,1.09,20.7h3.87l-2.76-30Z"></path><path style="fill:#fff" d="M33.56,20.24,27,50.29h3.9l1.14-5.86h6l1.13,5.86h4l-6.45-30ZM32.63,41.3c1-5,2-10.25,2.45-15.22.51,5.33,1.39,10.22,2.35,15.22Z"></path><path style="fill:#fff" d="M54.38,42.06c-.18,3.14.13,4.68-2.92,4.81-3.2-.19-2.76-2-3-5.39V20.24h-4V41.48c0,6.08.94,8.94,6.85,9.18,5.6-.16,6.95-2.63,7-8.6V20.24h-4Z"></path><rect style="fill:#fff" x="60.98" y="20.24" width="4.05" height="30.05"></rect></svg>.NET MAUI (FREE)</a><a tabindex="-1" href="https://www.devexpress.com/xamarin/"><svg data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 72" width="72px" height="72px"><title xmlns=""></title><path style="fill:#26a4dd" d="M66.6,0H5.4A5.42,5.42,0,0,0,0,5.4V66.6A5.42,5.42,0,0,0,5.4,72H66.6A5.42,5.42,0,0,0,72,66.6V5.4A5.42,5.42,0,0,0,66.6,0Z"></path><path style="fill:#fff" d="M39.5,20.24l-1.94,6.22-.27.87c-.2.63-.38,1.25-.56,1.88s-.33,1.27-.48,1.93a30,30,0,0,0-1.46-5.06L32.7,20.24h-4l5.36,14.85L28.4,50.4h4.3l1.74-5.47.35-1.13.68-2.15a13.36,13.36,0,0,0,.53-2.5,20.05,20.05,0,0,0,.53,2.42c.24.91.57,1.94,1,3.09l2,5.74h4.06L38,35.09,43.6,20.24Z"></path></svg>Xamarin UI Controls (FREE)</a>
<div class="h-clear">
</div>
</div>
<div class="column">
<div class="GroupTitle"> WEB CONTROLS </div>
<a tabindex="-1" href="https://js.devexpress.com/"><svg width="36px" height="36px" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg"><title xmlns=""></title><g clip-path="url(#clip0_1311_1312)"><rect width="36" height="36" rx="3" fill="white"></rect><path fill-rule="evenodd" clip-rule="evenodd" d="M2.808 0C1.26 0 0 1.25969 0 2.8073V21.1717C6.372 14.5314 17.64 7.76506 34.614 5.38965C35.244 5.29968 35.694 5.23669 36 5.18271V2.8073C36 1.25069 34.74 0 33.192 0L2.808 0Z" fill="#26A4DD"></path><path fill-rule="evenodd" clip-rule="evenodd" d="M33.183 36H2.808V35.991C1.269 35.991 0.018 34.7493 0 33.2107C0.009 32.7968 0.279 32.113 0.414 31.843C0.828 31.0153 1.521 29.9085 2.493 28.8018C8.028 21.8735 18.558 12.4619 35.991 9.42065V33.1927C35.991 34.7403 34.74 36 33.183 36ZM31.248 26.0935C30.798 25.3736 30.222 24.7168 29.547 24.1409C29.079 23.727 28.728 23.4031 28.467 23.1422C27.036 21.7115 27.702 20.6498 28.008 20.3529C28.143 20.2179 28.314 20.1009 28.512 20.029C28.71 19.957 28.917 19.921 29.133 19.921C29.709 19.948 30.249 20.1369 30.699 20.4519L31.05 20.7038V18.3824L30.924 18.3194C30.276 18.0225 29.547 17.8605 28.827 17.8605H28.8C28.323 17.8425 27.819 17.9145 27.369 18.0855C26.919 18.2564 26.505 18.5083 26.172 18.8413C23.652 21.3606 26.19 24.078 26.469 24.3479C26.766 24.6538 27.162 25.0227 27.738 25.5356C28.053 25.8145 28.323 26.0755 28.539 26.3094C28.71 26.4984 28.872 26.6963 29.007 26.9033C29.232 27.2632 29.34 27.6771 29.331 28.0999C29.358 28.5138 29.214 28.9187 28.926 29.2337C28.791 29.3686 28.62 29.4766 28.431 29.5486C28.242 29.6206 28.026 29.6476 27.819 29.6476C27.144 29.6026 26.514 29.3866 26.001 28.9997L25.641 28.7388V31.0422L25.74 31.1052C26.379 31.5461 27.171 31.789 27.972 31.789H28.134C28.593 31.789 29.061 31.6991 29.493 31.5371C29.952 31.3571 30.357 31.0962 30.699 30.7543C31.401 30.0075 31.77 29.0537 31.734 28.091C31.761 27.3981 31.599 26.7053 31.257 26.0755L31.248 26.0935ZM22.869 18.0585H20.421V28.262C20.421 28.7569 20.331 29.6836 19.341 29.6836C18.9 29.6386 18.477 29.5037 18.117 29.2787L17.775 29.0718V31.3842L17.91 31.4472C18.432 31.6811 19.008 31.8071 19.584 31.8071H19.683C19.728 31.8071 19.7708 31.8094 19.8135 31.8116C19.8563 31.8139 19.899 31.8161 19.944 31.8161C20.367 31.8161 20.781 31.7351 21.159 31.5822C21.627 31.3932 22.869 30.8353 22.869 28.361V18.0585Z" fill="#26A4DD"></path></g><defs><clipPath id="clip0_1311_1312"><rect width="36" height="36" rx="3" fill="white"></rect></clipPath></defs></svg>JavaScript – jQuery, Angular, React, Vue</a><a tabindex="-1" href="https://www.devexpress.com/blazor/"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 72" width="72px" height="72px"><title xmlns=""></title><path style="fill:#26a4dd" d="M66.6,0H5.4A5.42,5.42,0,0,0,0,5.4V66.6A5.42,5.42,0,0,0,5.4,72H66.6A5.42,5.42,0,0,0,72,66.6V5.4A5.42,5.42,0,0,0,66.6,0Z"></path><polygon style="fill:#fff" points="43.55 20.06 43.55 23.51 51.66 23.51 42.48 50.34 56.4 50.34 56.4 46.77 47.79 46.77 56.89 20.06 43.55 20.06"></polygon><polygon style="fill:#fff" points="34.08 20.06 30 20.06 30 50.34 40.75 50.34 40.75 46.89 34.08 46.89 34.08 20.06"></polygon><path style="fill:#fff" d="M23.31,34.94a5.29,5.29,0,0,0,3-2.25,9.62,9.62,0,0,0,.84-4.57q0-8.07-6.49-8.06H15.11V50.34h5.33q7.14,0,7.14-8.33a8.82,8.82,0,0,0-.92-4.55A6.56,6.56,0,0,0,23.31,34.94ZM19,23.35a.69.69,0,0,1,.2,0h.49q3.52,0,3.53,4.91a6.74,6.74,0,0,1-.92,4.06A4.16,4.16,0,0,1,19,33.39Zm3.47,22.42c-.64.72-1.79,1.08-3.47,1.08V36.63a4.27,4.27,0,0,1,3.44,1.18c.66.77,1,2.12,1,4.06S23.06,45.05,22.42,45.77Z"></path></svg>Blazor</a><a tabindex="-1" href="https://www.devexpress.com/products/net/controls/asp/"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 72" width="72px" height="72px"><title xmlns=""></title><path style="fill:#26a4dd" d="M66.6,0H5.4A5.42,5.42,0,0,0,0,5.4V66.6A5.42,5.42,0,0,0,5.4,72H66.6A5.42,5.42,0,0,0,72,66.6V5.4A5.42,5.42,0,0,0,66.6,0Z"></path><path style="fill:#fff" d="M51.36,20.24H46V50.4h4.06V37a13,13,0,0,0,5.14-.8c2.36-1.17,3.53-3.76,3.53-7.77,0-2.85-.58-4.94-1.75-6.25S53.94,20.24,51.36,20.24Zm2.19,12.29c-.64.68-1.8,1-3.48,1V23.66h.57a3.46,3.46,0,0,1,3,1.25,6.68,6.68,0,0,1,.94,3.95A5.36,5.36,0,0,1,53.55,32.53Z"></path><path style="fill:#fff" d="M19.08,20.24,12.51,50.4h3.91l1.15-5.88h6l1.13,5.88h4L22.24,20.24Zm-.94,21.14.74-3.87q.59-3.12,1-5.91c.28-1.85.52-3.69.7-5.5.38,3.71.86,7.2,1.46,10.47l.9,4.81Z"></path><path style="fill:#fff" d="M38.31,34.09c-.89-.9-1.63-1.67-2.19-2.3a10.82,10.82,0,0,1-1.22-1.57,4.86,4.86,0,0,1-.73-2.71,4,4,0,0,1,1-2.87,3.34,3.34,0,0,1,2.62-1.13,6,6,0,0,1,3.34,1.32v-4a8.83,8.83,0,0,0-4.14-1,6.32,6.32,0,0,0-5,2.09,8.12,8.12,0,0,0-1.84,5.61,8.9,8.9,0,0,0,.94,4.33,12.37,12.37,0,0,0,1.5,2.06c.68.78,1.53,1.68,2.56,2.69.66.66,1.22,1.27,1.66,1.81a11.9,11.9,0,0,1,1,1.43,6,6,0,0,1,.73,2.95,4.51,4.51,0,0,1-.94,3,3.22,3.22,0,0,1-2.6,1.1,6.86,6.86,0,0,1-3.94-1.58v4a7,7,0,0,0,4.43,1.42,6.46,6.46,0,0,0,5.06-2.21,8.48,8.48,0,0,0,2-5.76,9.52,9.52,0,0,0-.9-4.35A17.82,17.82,0,0,0,38.31,34.09Z"></path></svg>ASP.NET Web Forms</a><a tabindex="-1" href="https://www.devexpress.com/products/net/controls/asp/mvc/"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 72" width="72px" height="72px"><title xmlns=""></title><path style="fill:#26a4dd" d="M66.6,0H5.4A5.42,5.42,0,0,0,0,5.4V66.6A5.42,5.42,0,0,0,5.4,72H66.6A5.42,5.42,0,0,0,72,66.6V5.4A5.42,5.42,0,0,0,66.6,0Z"></path><path style="fill:#fff" d="M51,23.81q-2.24,3.95-2.23,12,0,14.94,9.14,14.94A6.55,6.55,0,0,0,61.15,50V46.23a6.16,6.16,0,0,1-2.4.62Q53,46.85,53,35.69a39.73,39.73,0,0,1,.32-5.37,14,14,0,0,1,1-3.75,5.22,5.22,0,0,1,1.71-2.2,4.31,4.31,0,0,1,2.48-.71,6.21,6.21,0,0,1,2.61.76V20.77a6.94,6.94,0,0,0-3.35-.9A7.36,7.36,0,0,0,51,23.81Z"></path><path style="fill:#fff" d="M25.05,20.28,22.69,32.36l-.45,2.16-.51,3.28-.56,3.45a1.1,1.1,0,0,0,0,.27q0,.18-.06.51c-.22-1.69-.47-3.3-.73-4.84s-.57-3.08-.89-4.62L16.8,20.28H13.32L10.85,50.4h3.82l1.17-20.75c.21,1.69.44,3.3.69,4.84s.55,3.06.87,4.56L19.78,50.4h2.73l2.54-13.15.19-1,.51-2.75c.06-.36.14-.81.22-1.35s.18-1.15.29-1.87l.09-.6a2.47,2.47,0,0,1,0,.34,1.26,1.26,0,0,1,0,.16l.1,3.71.18,4c0,.24,0,.56,0,.93s0,.83.06,1.35l.69,10.22h3.88L28.56,20.28Z"></path><path style="fill:#fff" d="M41.49,31.4c-.05.28-.11.59-.17.94s-.12.73-.18,1.15l-.68,4.58-.53,3.49c0,.16,0,.36-.08.59s-.06.5-.1.8l-.19-1.48c-.07-.5-.14-1-.22-1.66s-.18-1.29-.29-2l-.64-4.37-.31-2L36.28,20.28h-4L38.1,50.4h3.22l5.91-30.12H43.44Z"></path></svg>ASP.NET MVC</a><a tabindex="-1" href="https://www.devexpress.com/products/net/controls/asp/core.xml"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 72" width="72px" height="72px"><title xmlns=""></title><path style="fill:#26a4dd" d="M66.6,0H5.4A5.42,5.42,0,0,0,0,5.4V66.6A5.42,5.42,0,0,0,5.4,72H66.6A5.42,5.42,0,0,0,72,66.6V5.4A5.42,5.42,0,0,0,66.6,0Z"></path><path style="fill:#fff" d="M32.63,28.27c.68.78,1.53,1.68,2.56,2.69.66.67,1.22,1.27,1.66,1.81a11.18,11.18,0,0,1,1,1.44,5.89,5.89,0,0,1,.73,2.95,4.48,4.48,0,0,1-.94,3,3.22,3.22,0,0,1-2.6,1.11,6.93,6.93,0,0,1-3.94-1.58v4a7,7,0,0,0,4.43,1.43,6.49,6.49,0,0,0,5.06-2.21,8.48,8.48,0,0,0,2-5.76,9.6,9.6,0,0,0-.9-4.36,18,18,0,0,0-3.38-4.35c-.89-.9-1.63-1.67-2.19-2.31a11.43,11.43,0,0,1-1.22-1.56,4.89,4.89,0,0,1-.73-2.72,4,4,0,0,1,1-2.87,3.38,3.38,0,0,1,2.62-1.13,5.93,5.93,0,0,1,3.34,1.33v-4a8.82,8.82,0,0,0-4.14-1,6.29,6.29,0,0,0-5,2.09,8.11,8.11,0,0,0-1.84,5.6,8.94,8.94,0,0,0,.94,4.34A12.35,12.35,0,0,0,32.63,28.27Z"></path><path style="fill:#fff" d="M51.36,14.6H46V44.75h4.06V31.38a12.84,12.84,0,0,0,5.14-.81c2.36-1.17,3.53-3.76,3.53-7.77q0-4.28-1.75-6.25C55.81,15.25,53.94,14.6,51.36,14.6Zm2.19,12.28q-1,1-3.48,1V18h.57a3.44,3.44,0,0,1,3,1.25,6.62,6.62,0,0,1,.94,3.94A5.34,5.34,0,0,1,53.55,26.88Z"></path><polygon style="fill:#fff" points="47.2 54.66 49.83 54.66 49.83 52.91 47.2 52.91 47.2 50.29 50.01 50.29 50.01 48.55 45.18 48.55 45.18 59.05 50.19 59.05 50.19 57.31 47.2 57.31 47.2 54.66"></polygon><path style="fill:#fff" d="M41.76,54.24v0a2.71,2.71,0,0,0,1.86-2.82c0-1.89-1-2.83-3.16-2.83H37.53v10.5h2V55h.3c.5,0,.89.49,1.18,1.47l.75,2.56h2.26L43.1,56.1C42.76,55.05,42.32,54.43,41.76,54.24Zm-.6-1.41a1.18,1.18,0,0,1-1,.46h-.63v-3h.63a1.26,1.26,0,0,1,1,.39,1.59,1.59,0,0,1,.34,1.06A1.76,1.76,0,0,1,41.16,52.83Z"></path><path style="fill:#fff" d="M24.68,44.75h4L22.24,14.6H19.08L12.51,44.75h3.91l1.15-5.87h6Zm-6.54-9,.74-3.87q.59-3.12,1-5.9c.28-1.86.52-3.69.7-5.5.38,3.71.86,7.2,1.46,10.47l.9,4.8Z"></path><path style="fill:#fff" d="M22.94,49.84A6.76,6.76,0,0,0,21.81,54a6,6,0,0,0,1.09,3.8,3.57,3.57,0,0,0,3,1.39,4,4,0,0,0,2-.49V56.86a2.91,2.91,0,0,1-1.73.6,1.84,1.84,0,0,1-1.65-1,5,5,0,0,1-.6-2.65,5,5,0,0,1,.63-2.72,1.9,1.9,0,0,1,1.7-1,2.71,2.71,0,0,1,1.65.55v-2a4.26,4.26,0,0,0-1.76-.36A3.77,3.77,0,0,0,22.94,49.84Z"></path><path style="fill:#fff" d="M32.41,48.37a3.24,3.24,0,0,0-2.82,1.46,7.22,7.22,0,0,0-1,4.11,6.73,6.73,0,0,0,1,3.9,3.16,3.16,0,0,0,2.75,1.39,3.2,3.2,0,0,0,2.81-1.42,7.05,7.05,0,0,0,1-4,7.19,7.19,0,0,0-.94-4A3.12,3.12,0,0,0,32.41,48.37Zm1.17,8.16a1.33,1.33,0,0,1-1.22.93c-1.12,0-1.67-1.21-1.67-3.65s.57-3.67,1.71-3.67S34,51.38,34,53.87A6.65,6.65,0,0,1,33.58,56.53Z"></path></svg>ASP.NET Core</a><a tabindex="-1" href="https://www.devexpress.com/products/net/controls/asp/bootstrap-webforms.xml"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 72" width="72px" height="72px"><title xmlns=""></title><path style="fill:#26a4dd" d="M66.6,0H5.4A5.42,5.42,0,0,0,0,5.4V66.6A5.42,5.42,0,0,0,5.4,72H66.6A5.42,5.42,0,0,0,72,66.6V5.4A5.42,5.42,0,0,0,66.6,0Z"></path><path style="fill:#fff" d="M44.42,34.13V34a7.2,7.2,0,0,0,3.21-2.53,6.76,6.76,0,0,0,1.12-3.93,6.65,6.65,0,0,0-2.46-5.65,10.55,10.55,0,0,0-6.55-1.87H25V50.4H38.94A17.14,17.14,0,0,0,44,49.74,10.14,10.14,0,0,0,47.48,48a6.63,6.63,0,0,0,2-2.67A8.59,8.59,0,0,0,50.11,42a8.79,8.79,0,0,0-1.44-5.17A6.65,6.65,0,0,0,44.42,34.13ZM30.31,24.39H39a5.14,5.14,0,0,1,3.31.93,3.94,3.94,0,0,1,1.15,3.23,3.89,3.89,0,0,1-1.27,3.13A4.73,4.73,0,0,1,39,32.77H30.31ZM43.46,44.81a5.26,5.26,0,0,1-3.76,1.26H30.31V36.58H39.7a5.35,5.35,0,0,1,3.76,1.21,4.43,4.43,0,0,1,1.34,3.47A4.63,4.63,0,0,1,43.46,44.81Z"></path></svg>Bootstrap Web Forms</a><a tabindex="-1" href="https://www.devexpress.com/subscriptions/reporting/"><svg data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 72" width="72px" height="72px"><title xmlns=""></title><path style="fill:#26a4dd" d="M5.4,72H66.6A5.42,5.42,0,0,0,72,66.6V5.4A5.42,5.42,0,0,0,66.6,0H5.4A5.42,5.42,0,0,0,0,5.4V66.6A5.42,5.42,0,0,0,5.4,72Z"></path><polygon style="fill:#fff" points="45 16 45 24 53 24 45 16"></polygon><path style="fill:#fff" d="M36,39c5.52,0,10-1.79,10-4H35l3.83-3.83A23.15,23.15,0,0,0,36,31c-5.52,0-10,1.79-10,4S30.48,39,36,39Z"></path><path style="fill:#fff" d="M20,56H52a1,1,0,0,0,1-1V52H48V48l2,2h3L67,36l-5-5-9,9V25H44V16H20a1,1,0,0,0-1,1V55A1,1,0,0,0,20,56ZM63,36l1,1L53,48l-1-1Zm-2-2,1,1L51,46l-1-1ZM25,35c0-2.76,4.92-5,11-5s11,2.24,11,5v6c0,2.76-4.92,5-11,5s-11-2.24-11-5Z"></path></svg>Web Reporting</a>
<div class="h-clear">
</div>
<div class="GroupTitle"> FRAMEWORKS & PRODUCTIVITY </div>
<a tabindex="-1" href="https://www.devexpress.com/products/net/application_framework/"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 72" width="72px" height="72px"><title xmlns=""></title><path style="fill:#26a4dd" d="M66.6,0H5.4A5.42,5.42,0,0,0,0,5.4V66.6A5.42,5.42,0,0,0,5.4,72H66.6A5.42,5.42,0,0,0,72,66.6V5.4A5.42,5.42,0,0,0,66.6,0Z"></path><path style="fill:#fff" d="M35,20.24,28.44,50.33,22.88,35.09l5.58-14.85h-4.1l-1.93,6.22-.28.87c-.19.63-.38,1.25-.55,1.88s-.34,1.27-.48,1.93a31.26,31.26,0,0,0-1.47-5.06l-2.09-5.84H13.62L19,35.09,13.27,50.4h4.29l1.74-5.47.35-1.13.69-2.15a14.2,14.2,0,0,0,.52-2.5,22.18,22.18,0,0,0,.53,2.42c.25.91.57,1.94,1,3.09l2,5.74h8l1.15-5.88h6l1.13,5.88h4L38.15,20.24Zm-.93,21.14.74-3.87q.59-3.12,1-5.91c.29-1.85.53-3.69.71-5.5.38,3.71.86,7.2,1.46,10.47l.9,4.81Z"></path><polygon style="fill:#fff" points="47 50.4 51.06 50.4 51.06 36.65 57.19 36.65 57.19 33.21 51.06 33.21 51.06 23.68 57.85 23.68 57.85 20.24 47 20.24 47 50.4"></polygon></svg>XAF - Cross-Platform .NET App UI</a><a tabindex="-1" href="https://www.devexpress.com/products/net/orm/"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 72" width="72px" height="72px"><title xmlns=""></title><path style="fill:#26a4dd" d="M66.6,0H5.4A5.42,5.42,0,0,0,0,5.4V66.6A5.42,5.42,0,0,0,5.4,72H66.6A5.42,5.42,0,0,0,72,66.6V5.4A5.42,5.42,0,0,0,66.6,0Z"></path><path style="fill:#fff" d="M36,14c-9.94,0-18,2.69-18,6v6c0,3.31,8.06,6,18,6s18-2.69,18-6V20C54,16.69,45.94,14,36,14Zm0,10c-7.73,0-14-1.79-14-4s6.27-4,14-4,14,1.79,14,4S43.73,24,36,24Z"></path><path style="fill:#fff" d="M36,34c-7.83,0-14.48-1.67-16.95-4A2.82,2.82,0,0,0,18,32v6c0,3.31,8.06,6,18,6s18-2.69,18-6V32a2.82,2.82,0,0,0-1-2C50.48,32.33,43.83,34,36,34Z"></path><path style="fill:#fff" d="M36,46c-7.83,0-14.48-1.67-16.95-4A2.82,2.82,0,0,0,18,44v6c0,3.31,8.06,6,18,6s18-2.69,18-6V44a2.82,2.82,0,0,0-1-2C50.48,44.33,43.83,46,36,46Z"></path></svg>XPO – ORM Library (FREE)</a><a tabindex="-1" href="https://www.devexpress.com/products/net/application_framework/security-web-api-service.xml"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 72" width="72px" height="72px"><title xmlns=""></title><path style="fill:#26a4dd" d="M66.6,0H5.4A5.42,5.42,0,0,0,0,5.4V66.6A5.42,5.42,0,0,0,5.4,72H66.6A5.42,5.42,0,0,0,72,66.6V5.4A5.42,5.42,0,0,0,66.6,0Z"></path><path style="fill:#fff" d="M58.87,18.53c-6.49,0-9.7-3.21-10.83-9.53H24c-1.13,6.32-4.34,9.53-10.83,9.53l-1,10.29a35.52,35.52,0,0,0,.1,8C14,48.6,21.29,57,32.22,62.93L36,65l3.78-2.07C50.71,57,58.05,48.6,59.71,36.87a34.4,34.4,0,0,0,.1-8ZM55.75,36c-1.4,9.71-7.37,17.29-18.24,23.15L36,60l-1.51-.81C23.61,53.33,17.65,45.75,16.25,36a30,30,0,0,1-.08-7.14l.62-6.61A14.06,14.06,0,0,0,27.29,13H44.7a14.09,14.09,0,0,0,10.51,9.29l.62,6.6A30.6,30.6,0,0,1,55.75,36Z"></path><path style="fill:#fff" d="M51.43,25a14.86,14.86,0,0,1-9-8H36V55l.27-.15c9.27-5,14.35-11.32,15.52-19.42a24.61,24.61,0,0,0,.06-6Z"></path></svg>.NET App Security & Web API Service (FREE)</a><a tabindex="-1" href="https://www.devexpress.com/products/coderush/"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 72" width="72px" height="72px"><title xmlns=""></title><path style="fill:#26a4dd" d="M66.6,0H5.4A5.42,5.42,0,0,0,0,5.4V66.6A5.42,5.42,0,0,0,5.4,72H66.6A5.42,5.42,0,0,0,72,66.6V5.4A5.42,5.42,0,0,0,66.6,0Z"></path><path style="fill:#fff" d="M36,10A26,26,0,1,0,62,36,26,26,0,0,0,36,10Zm7,38H29L22,36l7-12H43l7,12Z"></path></svg>CodeRush for Visual Studio (FREE)</a>
<div class="h-clear">
</div>
<div class="GroupTitle"> TESTING & QA </div>
<a tabindex="-1" href="https://www.devexpress.com/products/testcafestudio"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 72" width="72px" height="72px"><title xmlns=""></title><path style="fill:#26a4dd" d="M5.4,72H66.6A5.42,5.42,0,0,0,72,66.6V5.4A5.42,5.42,0,0,0,66.6,0H5.4A5.42,5.42,0,0,0,0,5.4V66.6A5.42,5.42,0,0,0,5.4,72Z"></path><polygon style="fill:#fff" points="61 20 56 15 35 36 27 28 22 33 35 46 61 20"></polygon><polygon style="fill:#fff" points="51 41 42 41 40 43 49 43 57 50 15 50 23 43 30 43 28 41 21 41 7 53 65 53 51 41"></polygon></svg>TestCafe Studio</a>
<div class="h-clear">
</div>
</div>
</div>
</div>
</div>
<div class="MenuFooter">
<div class="content">
<div class="column">
<a href="https://www.devexpress.com/subscriptions/whats-new/">What's New</a><a href="https://www.devexpress.com/dotnet-core/">.NET 8 Support</a>
</div>
</div>
</div>
<div class="Shadow hidden-md">
</div>
</div>
</li>
<li class="divider"></li>
<li><a tabindex="-1" href="https://www.devexpress.com/support/demos/">Demos</a></li>
<li class="divider"></li>
<li><a tabindex="-1" href="https://www.devexpress.com/buy/">Buy</a></li>
<li class="divider"></li>
<li><a tabindex="-1" href="javascript:;">Support & Docs</a>
<div class="SubMenu Support">
<div class="Header hidden-md">
<span>Support & Docs</span>
<div class="CloseButton">
</div>
</div>
<div class="r-container">
<div class="ScrollContainer">
<div class="column">
<div class="GroupTitle"> SUPPORT CENTER </div><a tabindex="-1" href="https://supportcenter.devexpress.com/ticket/list"><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 36 36" style="enable-background:new 0 0 36 36;" xml:space="preserve" width="36px" height="36px"><title xmlns=""></title>
<path style="fill:#FF7200" d="M30.3,5.2L32.4,0l-5,3.6c-1.9-0.8-4.1-1.2-6.4-1.2c-8.3,0-15,5.7-15,12.7c0,0.2,0,0.4,0,0.5
c-3.6,1.6-6,4.8-6,8.5c0,2.1,0.8,4,2.1,5.6L0,35l4.5-3.2c1.9,1.3,4.3,2,6.9,2c4.8,0,8.9-2.5,10.6-6.1c7.8-0.4,14-5.9,14-12.6
C36,11.1,33.8,7.5,30.3,5.2z M11.4,30.2c-4.3,0-7.8-2.7-7.8-6s3.5-6,7.8-6s7.8,2.7,7.8,6S15.7,30.2,11.4,30.2z M22.8,24
c-0.1-5.3-5.1-9.5-11.4-9.5c-0.6,0-1.2,0.1-1.8,0.1C9.9,9.8,14.9,6,21,6c6.3,0,11.4,4.1,11.4,9.1C32.4,19.6,28.2,23.3,22.8,24z"></path>
</svg>Search the KB</a><a tabindex="-1" href="https://supportcenter.devexpress.com/ticket/list?preset=mytickets"><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 36 36" style="enable-background:new 0 0 36 36;" xml:space="preserve" width="36px" height="36px"><title xmlns=""></title>
<path style="fill:#FF7200" d="M28.4,7H1.6C0.7,7,0,7.7,0,8.6v24.7c0,1,0.7,1.7,1.6,1.7h26.7c0.9,0,1.6-0.7,1.6-1.6V8.6
C30,7.7,29.3,7,28.4,7z M14.3,31c-1.4,0-2.3-0.5-2.3-2.1s0.9-2.2,2.3-2.2s2.3,0.5,2.3,2.2C16.6,30.5,15.7,31,14.3,31z M16,25.3h-3.1
c-1.7-5,4.9-5.5,4.9-9.1c0-1.6-1.2-2.1-2.8-2.1c-0.6,0-1.5,0.1-2.2,0.5c-0.1,0.9-0.3,1.8-0.5,2.4H9.7c-0.5-1-0.8-3-0.7-4.2
c1.6-1.1,4.1-1.7,6.1-1.7c3.8,0,6.9,1.8,6.9,5.5C22,21.5,15.7,21.9,16,25.3z"></path>
<path style="fill:#FF7200" d="M33,29h-1V8c0-1.7-1.3-3-3-3H6V4c0-1.7,1.3-3,3-3h24c1.7,0,3,1.3,3,3v22C36,27.7,34.7,29,33,29z"></path>
</svg>My Questions</a><a tabindex="-1" href="https://localization.devexpress.com/"><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 36 36" style="enable-background:new 0 0 36 36;" xml:space="preserve" width="36px" height="36px"><title xmlns=""></title>
<path style="fill:#FF7200" d="M27,18c-5,0-9,4-9,9c0,5,4,9,9,9s9-4,9-9C36,22,32,18,27,18z M30.7,33h-1.9l-0.5-1.5h-0.1
c-0.4,0.6-0.8,1.1-1.2,1.3s-0.9,0.4-1.6,0.4c-0.8,0-1.4-0.3-1.9-0.9s-0.7-1.4-0.7-2.5c0-1.1,0.3-2,0.9-2.6s1.6-0.9,2.8-0.9l1.4-0.1
v-0.8c0-1-0.4-1.5-1.3-1.5c-0.7,0-1.4,0.3-2.2,0.8l-0.9-1.8c1.1-0.7,2.3-1,3.5-1c1.2,0,2,0.3,2.6,1s0.9,1.6,0.9,2.8V33z M27.3,27.9
l0.8,0v0.9c0,0.7-0.1,1.3-0.4,1.7s-0.7,0.6-1.1,0.6c-0.6,0-1-0.4-1-1.3c0-0.6,0.1-1.1,0.4-1.4S26.7,28,27.3,27.9z M12.1,0.6
c-0.2,0.2-0.4,0.4-0.6,0.7c-0.6,0.6-1.2,1.2-1.8,1.6H7.9V2.6c0.3-0.3,0.6-0.8,0.9-1.5C9,0.7,9.2,0.3,9.4,0C9.3,0,9.1,0,9,0
C4,0,0,4,0,9c0,5,4,9,9,9s9-4,9-9C18,5.1,15.6,1.8,12.1,0.6z M12.7,15h-1.9l-0.5-1.5h-0.1c-0.4,0.6-0.8,1.1-1.2,1.3
c-0.4,0.2-0.9,0.4-1.6,0.4c-0.8,0-1.4-0.3-1.9-0.9s-0.7-1.4-0.7-2.5c0-1.1,0.3-2,0.9-2.6s1.6-0.9,2.8-0.9l1.4-0.1V7.5
c0-1-0.4-1.5-1.3-1.5C8.1,6,7.4,6.2,6.5,6.7L5.6,4.9c1.1-0.7,2.3-1,3.5-1c1.2,0,2,0.3,2.6,1s0.9,1.6,0.9,2.8V15z M9.3,9.9l0.8,0v0.9
c0,0.7-0.1,1.3-0.4,1.7S9,13.2,8.5,13.2c-0.6,0-1-0.4-1-1.3c0-0.6,0.1-1.1,0.4-1.4S8.7,10,9.3,9.9z M34.9,14.9
c0.1,0.7-0.7,1.3-1.4,1c0,0,0,0,0,0c-0.3-0.1-0.5-0.4-0.6-0.8c-0.6-4.6-3.7-8.4-7.8-10.1L24,8l-4-6l7-2l-1.2,3.2
C30.6,5.2,34.1,9.6,34.9,14.9z M12,28l4,6l-7,2l1.2-3.2c-4.8-2-8.3-6.4-9-11.8c-0.1-0.7,0.7-1.3,1.4-1c0,0,0,0,0,0
c0.3,0.1,0.5,0.4,0.6,0.8c0.6,4.6,3.7,8.4,7.8,10.1L12,28z"></path>
</svg>Localization</a><a tabindex="-1" href="https://www.devexpress.com/Support/Versions.xml"><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 36 36" style="enable-background:new 0 0 36 36;" xml:space="preserve" width="36px" height="36px"><title xmlns=""></title>
<path style="fill:#FF7200" d="M18,36C8.8,36,1.3,29.1,0.1,20.3C0,19.1,0.9,18,2.1,18c1,0,1.9,0.8,2,1.8C5,26.7,10.9,32,18,32
c8.3,0,14.8-7.1,13.9-15.6c-0.7-6.2-5.6-11.3-11.8-12.2c-4-0.6-7.7,0.5-10.6,2.7L13,10L2,12L3,1l3.5,3.2c3.4-2.9,8-4.5,12.9-4.1
C27.9,0.7,35,7.5,35.9,16C37.1,26.8,28.6,36,18,36z M11,26l1,1l7-9l7,1l1-2l-10-4L11,26z"></path>
</svg>Version History</a><a tabindex="-1" href="https://www.devexpress.com/subscriptions/whats-new/"><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 36 36" style="enable-background:new 0 0 36 36;" xml:space="preserve" width="36px" height="36px"><title xmlns=""></title>
<path style="fill:#FF7200" d="M2,0v36h32V6h-6V0H2z M32,34H4V2h22v6h6V34z"></path>
<rect style="fill:#FF7200" x="19" y="12" width="9" height="10"></rect>
<rect style="fill:#FF7200" x="8" y="6" width="9" height="2"></rect>
<rect style="fill:#FF7200" x="8" y="12" width="9" height="4"></rect>
<rect style="fill:#FF7200" x="8" y="18" width="9" height="12"></rect>
<rect style="fill:#FF7200" x="19" y="24" width="9" height="6"></rect>
</svg>What's New in the Latest Version</a>
<div class="h-clear">
</div>
</div>
<div class="column">
<div class="GroupTitle"> LEARNING MATERIALS </div><a tabindex="-1" href="https://docs.devexpress.com/"><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 36 36" style="enable-background:new 0 0 36 36;" xml:space="preserve" width="36px" height="36px"><title xmlns=""></title>
<path style="fill:#FF7200" d="M34,9.3v20.5c-3.4-2.5-16-3.8-16,1.1L36,32V9.9L34,9.3z"></path>
<path style="fill:#FF7200" d="M2,9.3v20.5c3.4-2.5,16-3.8,16,1.1L0,32L0,9.9L2,9.3z"></path>
<path style="fill:#FF7200" d="M18,6.8C18,0.3,4,7.2,4,7.2v19.4c0,0,14-5.3,14,0.7c0-6,14-0.7,14-0.7V7.2C32,7.2,18,0.3,18,6.8z"></path>
</svg>Documentation</a><a tabindex="-1" href="https://supportcenter.devexpress.com/ticket/list?preset=examples"><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 36 36" style="enable-background:new 0 0 36 36;" xml:space="preserve" width="36px" height="36px"><title xmlns=""></title>
<path style="fill:#FF7200" d="M2.8,6.1c0,1.1,0.1,2.3,0.2,3.6c0.1,1.2,0.3,2.4,0.3,3.5c0,1.4-0.3,3-3.3,3.1v3.5
c3,0.1,3.3,1.8,3.3,3.1c0,1.1-0.1,2.3-0.3,3.5c-0.1,1.2-0.2,2.4-0.2,3.6c0,4.5,2.7,6.1,6.6,6.1H11v-3.8h-0.8c-2,0-2.7-1.3-2.7-3.2
c0-0.8,0.1-1.6,0.2-2.5c0.1-0.9,0.2-2,0.2-3.2c0-3.4-1.3-4.7-3.7-5.3v-0.1C6.7,17.4,8,16.1,8,12.7c0-1.1-0.1-2.2-0.2-3.1
C7.7,8.7,7.6,7.8,7.6,7c0-2,0.7-3.2,2.7-3.2H11V0H9.5C5.4,0,2.8,1.8,2.8,6.1z"></path>
<path style="fill:#FF7200" d="M32.7,13.2c0-1.1,0.1-2.3,0.3-3.5c0.1-1.2,0.2-2.4,0.2-3.6c0-4.2-2.6-6.1-6.6-6.1H25v3.8h0.8
c2,0,2.7,1.2,2.7,3.2c0,0.8-0.1,1.6-0.2,2.6c-0.1,0.9-0.2,1.9-0.2,3.1c0,3.4,1.3,4.7,3.7,5.2V18c-2.4,0.5-3.8,1.8-3.7,5.3
c0,1.2,0.1,2.2,0.2,3.2c0.1,0.9,0.2,1.8,0.2,2.5c0,2-0.7,3.2-2.7,3.2H25V36h1.6c3.9,0,6.6-1.6,6.6-6.1c0-1.1-0.1-2.3-0.2-3.6
c-0.1-1.2-0.3-2.4-0.3-3.5c0-1.3,0.3-3,3.3-3.1v-3.5C33,16.2,32.7,14.5,32.7,13.2z"></path>
</svg>Code Examples</a><a tabindex="-1" href="https://www.devexpress.com/support/demos/"><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 36 36" style="enable-background:new 0 0 36 36;" xml:space="preserve" width="36px" height="36px"><title xmlns=""></title>
<path style="fill:#FF7200" d="M31,21l5-0.5l0-5L31,15c-0.3-1.5-0.9-2.9-1.8-4.2l3.2-4l-3.2-3.2l-4,3.2C23.9,6,22.5,5.4,21,5l-0.5-5
h-5L15,5c-1.5,0.3-2.9,0.9-4.2,1.8l-4-3.2L3.6,6.8l3.2,4C6,12.1,5.4,13.5,5,15l-5,0.5v5L5,21c0.3,1.5,0.9,2.9,1.8,4.2l-3.2,4
l3.2,3.2l4-3.2c1.3,0.8,2.7,1.4,4.2,1.8l0.5,5h5l0.5-5c1.5-0.3,2.9-0.9,4.2-1.8l4,3.2l3.2-3.2l-3.2-4C30,23.9,30.6,22.5,31,21z
M18,27c-5,0-9-4-9-9c0-5,4-9,9-9c5,0,9,4,9,9C27,23,23,27,18,27z"></path>
</svg>Demos</a><a tabindex="-1" href="https://www.devexpress.com/trainingcenter/"><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 36 36" style="enable-background:new 0 0 36 36;" xml:space="preserve" width="36px" height="36px"><title xmlns=""></title>
<path style="fill:#FF7200" d="M34,3H19V1c0-0.5-0.4-1-1-1c0,0,0,0,0,0c-0.5,0-1,0.4-1,1v2H2C0.9,3,0,3.9,0,5v20c0,1.1,0.9,2,2,2h9
l-4,4c-0.6,0.6-0.6,1.4,0,2l0,0c0.6,0.6,1.4,0.6,2,0l6-6h1l0.9,8c0.1,0.6,0.5,1,1.1,1h0c0.6,0,1-0.4,1.1-1l0.9-8h1l6,6
c0.6,0.6,1.4,0.6,2,0l0,0c0.6-0.6,0.6-1.4,0-2l-4-4h9c1.1,0,2-0.9,2-2V5C36,3.9,35.1,3,34,3z M32,23H4V7h28V23z"></path>
</svg>Training</a>
<div class="h-clear">
</div>
</div>
</div>
</div>
<div class="MenuFooter">
<div class="content">
<div class="column">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 48 48" style="enable-background:new 0 0 48 48;" xml:space="preserve" width="48px" height="48px">
<title xmlns=""></title>
<path style="fill:#FF7200" d="M24,0C10.7,0,0,10.7,0,24s10.7,24,24,24s24-10.7,24-24S37.3,0,24,0z M34.7,36.8c-2.7,2.4-6.1,4-9.9,4.2
c-0.3,0.6-1,1-1.7,1c-1.1,0-2-0.9-2-2c0-1.1,0.9-2,2-2c0.7,0,1.3,0.4,1.7,0.9c3.3-0.2,6.3-1.5,8.7-3.6c0.4-0.4,1-0.4,1.3,0l0,0
C35.1,35.7,35.1,36.4,34.7,36.8z M35.5,34.1c-0.4,0.4-1,0.4-1.3,0l-0.1-0.1c-0.9,0.7-2,1.1-3.2,0.9l0,0c-0.5-0.1-0.9-0.6-0.8-1.1
l1.6-9c0.1-0.5,0.6-0.9,1.1-0.8l0.1,0c2.1,0.4,3.4,2.5,3,4.6l-0.4,2.2c1.5-2.2,2.5-5,2.5-7.9c0-8-6.6-14.4-14.7-14
c-6.8,0.3-12.5,5.7-13.2,12.5c-0.4,3.5,0.6,6.8,2.4,9.4l-0.4-2.2c-0.4-2.1,1-4.2,3-4.6l0.1,0c0.5-0.1,1,0.2,1.1,0.8l1.6,9
c0.1,0.5-0.2,1-0.8,1.1l0,0c-1.2,0.2-2.4-0.1-3.2-0.9l-0.1,0.1c-0.4,0.4-1,0.4-1.3,0C9.7,31.3,8,27.3,8,23c0-9.4,8.2-17,17.8-15.9
c7.2,0.8,13,6.5,14,13.7C40.6,26,38.7,30.8,35.5,34.1z"></path>
</svg>
<h6> Need help or require more information? </h6>
<p> Submit your support inquiries via the <a href="https://www.devexpress.com/Support/Center/">DevExpress Support Center</a> for assistance. </p>
</div>
</div>
</div>
<div class="Shadow hidden-md">
</div>
</div>
</li>
<li class="divider"></li>
<li><a tabindex="-1" href="https://community.devexpress.com/blogs/">Blogs<span class="Notification" data-menu-notification="NewBlogPosts/Count"></span></a></li>
<li class="divider"></li>
<li><a tabindex="-1" href="javascript:;">About Us</a>
<div class="SubMenu AboutUs">
<div class="Header hidden-md">
<span>About Us</span>
<div class="CloseButton">
</div>
</div>
<div class="r-container">
<div class="ScrollContainer">
<div class="column">
<div class="GroupTitle"> CONNECT WITH DEVEXPRESS </div><a tabindex="-1" href="https://community.devexpress.com/blogs/"><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 36 36" style="enable-background:new 0 0 36 36;" xml:space="preserve" width="36px" height="36px"><title xmlns=""></title>
<path style="fill:#FF7200" d="M11,16c-1.4,0-2.8,0.3-4,0.9V8.5C7,7.1,5.9,6,4.5,6S2,7.1,2,8.5V25c0,5,4,9,9,9s9-4,9-9
C20,20,16,16,11,16z M11,29c-2.2,0-4-1.8-4-4c0-2.2,1.8-4,4-4s4,1.8,4,4C15,27.2,13.2,29,11,29z"></path>
<path style="fill:#FF7200" d="M11,8v5c6.6,0,12,5.4,12,12h5C28,15.6,20.4,8,11,8z"></path>
<path style="fill:#FF7200" d="M11,0v5c11,0,20,9,20,20h5C36,11.2,24.8,0,11,0z"></path>
</svg>Blogs</a><a tabindex="-1" href="https://www.devexpress.com/aboutus/events/"><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 36 36" style="enable-background:new 0 0 36 36;" xml:space="preserve" width="36px" height="36px"><title xmlns=""></title>
<path style="fill:#FF7200" d="M34,4h-4v5c0,0.6-0.4,1-1,1h-4c-0.6,0-1-0.4-1-1V4H12v5c0,0.6-0.4,1-1,1H7c-0.6,0-1-0.4-1-1V4H2
C0.9,4,0,4.9,0,6v26c0,1.1,0.9,2,2,2h32c1.1,0,2-0.9,2-2V6C36,4.9,35.1,4,34,4z M26,14v4h-4v-4H26z M16,20h4v4h-4V20z M14,24h-4v-4
h4V24z M22,20h4v4h-4V20z M20,14v4h-4v-4H20z M14,14v4h-4v-4H14z M4,14h4v4H4V14z M4,20h4v4H4V20z M4,30v-4h4v4H4z M10,30v-4h4v4H10
z M16,30v-4h4v4H16z M22,30v-4h4v4H22z M32,30h-4v-4h4V30z M32,24h-4v-4h4V24z M32,18h-4v-4h4V18z"></path>
<path style="fill:#FF7200" d="M9,0L9,0C8.4,0,8,0.4,8,1v6c0,0.6,0.4,1,1,1h0c0.6,0,1-0.4,1-1V1C10,0.4,9.6,0,9,0z"></path>
<path style="fill:#FF7200" d="M27,0L27,0c-0.6,0-1,0.4-1,1v6c0,0.6,0.4,1,1,1h0c0.6,0,1-0.4,1-1V1C28,0.4,27.6,0,27,0z"></path>
</svg>Events, Meetups and Tradeshows</a>
<div class="h-clear">
</div>
</div>
<div class="column">
<div class="GroupTitle"> LEARN MORE ABOUT DEVEXPRESS </div><a tabindex="-1" href="https://www.devexpress.com/aboutus/"><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 36 36" style="enable-background:new 0 0 36 36;" xml:space="preserve" width="36px" height="36px"><title xmlns=""></title>
<circle style="fill:#FF7200" cx="18" cy="3" r="3"></circle>
<path style="fill:#FF7200" d="M21.5,7h-1.2h-4.5h-1.2C13.1,7,12,8.1,12,9.5V22c0,0.6,0.4,1,1,1h1v11c0,1.1,0.9,2,2,2h4
c1.1,0,2-0.9,2-2V21h1c0.6,0,1-0.4,1-1V9.5C24,8.1,22.9,7,21.5,7z"></path>
<circle style="fill:#FF7200" cx="5" cy="6" r="3"></circle>
<path style="fill:#FF7200" d="M7.5,10H6.2H3.8H2.5C1.1,10,0,11.1,0,12.5V19c0,0.6,0.4,1,1,1h1v12c0,1.1,0.9,2,2,2h2c1.1,0,2-0.9,2-2
v-8h1c0.6,0,1-0.4,1-1V12.5C10,11.1,8.9,10,7.5,10z"></path>
<circle style="fill:#FF7200" cx="31" cy="6" r="3"></circle>
<path style="fill:#FF7200" d="M33.5,10h-1.2h-2.5h-1.2c-1.4,0-2.5,1.1-2.5,2.5V23c0,0.6,0.4,1,1,1h1v8c0,1.1,0.9,2,2,2h2
c1.1,0,2-0.9,2-2v-9h1c0.6,0,1-0.4,1-1v-9.5C36,11.1,34.9,10,33.5,10z"></path>
</svg>About Us</a><a tabindex="-1" href="https://www.devexpress.com/aboutus/newsreviews/"><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 36 36" style="enable-background:new 0 0 36 36;" xml:space="preserve" width="36px" height="36px"><title xmlns=""></title>
<path style="fill:#FF7200" d="M2,0v36h32V6h-6V0H2z M32,34H4V2h22v6h6V34z"></path>
<rect style="fill:#FF7200" x="19" y="12" width="9" height="10"></rect>
<rect style="fill:#FF7200" x="8" y="6" width="9" height="2"></rect>
<rect style="fill:#FF7200" x="8" y="12" width="9" height="4"></rect>
<rect style="fill:#FF7200" x="8" y="18" width="9" height="12"></rect>
<rect style="fill:#FF7200" x="19" y="24" width="9" height="6"></rect>
</svg>News</a><a tabindex="-1" href="https://www.devexpress.com/aboutus/testimonials/"><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 36 36" style="enable-background:new 0 0 36 36;" xml:space="preserve" width="36px" height="36px"><title xmlns=""></title>
<path style="fill:#FF7200" d="M18,2C8.1,2,0,9.2,0,18c0,5.2,2.8,9.7,7,12.7C6,32,4.7,33.2,3,34c0,0,3.8,2.1,7.8,0.1c0.5-0.2,1-0.6,1.4-1
C14,33.7,16,34,18,34c9.9,0,18-7.2,18-16S27.9,2,18,2z M18,30c-7.7,0-14-5.4-14-12c0-6.6,6.3-12,14-12s14,5.4,14,12
C32,24.6,25.7,30,18,30z"></path>
<circle style="fill:#FF7200" cx="18" cy="18" r="2"></circle>
<circle style="fill:#FF7200" cx="24" cy="18" r="2"></circle>
<circle style="fill:#FF7200" cx="12" cy="18" r="2"></circle>
</svg>User Comments and Case Studies</a><a tabindex="-1" href="https://www.devexpress.com/aboutus/awards/"><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 36 36" style="enable-background:new 0 0 36 36;" xml:space="preserve" width="36px" height="36px"><title xmlns=""></title>
<path style="fill:#FF7200" d="M11.7,28.3L11.7,28.3c-0.6-1.1-1.7-1.8-3-1.7l0,0c-1.4,0.1-2.6-0.8-3.1-2L0,33l5-1l2,4l4.9-7.4
C11.9,28.5,11.8,28.4,11.7,28.3z"></path>
<path style="fill:#FF7200" d="M30.4,24.5c-0.5,1.2-1.7,2.1-3.1,2l0,0c-1.2-0.1-2.4,0.6-3,1.7l0,0c-0.1,0.1-0.1,0.2-0.2,0.3L29,36l2-4
l5,1L30.4,24.5z"></path>
<path style="fill:#FF7200" d="M31.6,15.5c-0.6-0.9-0.6-2.1,0-3l0,0c0.9-1.4,0.4-3.2-1.1-4l0,0C29.5,8,28.9,7,29,5.9l0,0
c0.1-1.6-1.3-3-2.9-2.9l0,0C25,3.1,24,2.5,23.5,1.5l0,0c-0.8-1.5-2.6-1.9-4-1.1l0,0c-0.9,0.6-2.1,0.6-3,0l0,0
c-1.4-0.9-3.2-0.4-4,1.1l0,0C12,2.5,11,3.1,9.9,3l0,0C8.3,2.9,6.9,4.3,7,5.9l0,0C7.1,7,6.5,8,5.5,8.5l0,0c-1.5,0.8-1.9,2.6-1.1,4
l0,0c0.6,0.9,0.6,2.1,0,3l0,0c-0.9,1.4-0.4,3.2,1.1,4l0,0C6.5,20,7.1,21,7,22.1l0,0c-0.1,1.6,1.3,3,2.9,2.9l0,0
c1.1-0.1,2.1,0.5,2.6,1.5l0,0c0.8,1.5,2.6,1.9,4,1.1l0,0c0.9-0.6,2.1-0.6,3,0l0,0c1.4,0.9,3.2,0.4,4-1.1l0,0c0.5-1,1.5-1.6,2.6-1.5
l0,0c1.6,0.1,3-1.3,2.9-2.9l0,0c-0.1-1.1,0.5-2.1,1.5-2.6l0,0C32,18.7,32.4,16.9,31.6,15.5L31.6,15.5z M18,25c-6.1,0-11-4.9-11-11
S11.9,3,18,3s11,4.9,11,11S24.1,25,18,25z"></path>
<path style="fill:#FF7200" d="M18,5c-5,0-9,4-9,9c0,5,4,9,9,9s9-4,9-9C27,9,23,5,18,5z M18,21c-3.9,0-7-3.1-7-7s3.1-7,7-7s7,3.1,7,7
S21.9,21,18,21z"></path>
</svg>Our Awards</a><a tabindex="-1" href="https://www.devexpress.com/aboutus/mvp/"><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 36 36" style="enable-background:new 0 0 36 36;" xml:space="preserve" width="36px" height="36px"><title xmlns=""></title>
<path style="fill:#FF7200" d="M18,0C8.1,0,0,8.1,0,18c0,9.9,8.1,18,18,18s18-8.1,18-18C36,8.1,27.9,0,18,0z M31.2,13.3h-9.9l-3-9.3
C24.3,4.2,29.3,8,31.2,13.3z M17.7,4l-3,9.3H4.8C6.7,8,11.7,4.2,17.7,4z M4,18c0-1.5,0.2-2.9,0.6-4.2l8,5.9l-3,9.5
C6.2,26.6,4,22.6,4,18z M10,29.5l8-5.9l8,5.9c-2.3,1.6-5,2.5-8,2.5S12.3,31.1,10,29.5z M26.4,29.2l-3-9.5l8-5.9
c0.4,1.3,0.6,2.7,0.6,4.2C32,22.6,29.8,26.6,26.4,29.2z"></path>
</svg>MVP Program</a>
<div class="h-clear">
</div>
</div>
</div>
</div>
<div class="MenuFooter">
<div class="content">
<div class="column">
<a href="https://www.devexpress.com/subscriptions/whats-new/"><h6>
Announcing DevExpress Universal v24.1
</h6></a>
<p>Developer Express Inc is proud to announce the immediate availability of its newest release, DevExpress v24.1. Built and optimized for desktop, web, and mobile developers alike...</p>
</div>
<div class="column">
<a href="https://www.devexpress.com/aboutus/awards/"><h6>
DevExpress Wins 19 Visual Studio Reader's Choice Awards
</h6></a>
<p> Like previous years, DevExpress dominated Visual Studio Magazine's 2023 Readers Choice Awards. We thank all our loyal users for casting their vote on behalf of DevExpress. </p>
</div>
</div>
</div>
<div class="Shadow hidden-md">
</div>
</div>
</li>
</ul>
<div class="h-clear">
</div>
</div>
</div>
</nav>
<section id="LightBox">
<section class="LightBox Shaded">
<div class="Background" style="background-image:url(/subscriptions/i/whats-new.jpg);">
</div>
<div class="BackgroundOverlay">
</div>
<div class="v-align" data-role="LightBoxContent">
<div class="align-row">
<div class="align-cell middle">
<div class="content">
<h2> When Only the Best Will Do </h2>
<h1> v24.1 IS NOW AVAILABLE </h1>
<p> Your skills, our tools.<br> Let's build great apps together. </p>
<div class="Buttons">
<a href="/products/try/" class="Button Orange" data-caption="Ready to evaluate v24.1?">Free 30-Day Trial</a><a href="https://www.devexpress.com/ClientCenter/DownloadManager/" class="Button Transparent" data-caption="Already own a license?">Download v24.1</a>
</div>
</div>
</div>
</div>
</div>
</section>
</section>
<main>
<section class="Platforms Gray">
<div class="content">
<div class="Index">
<h2> Explore Our Newest Features (v24.1) </h2>
<div class="WhatsNewTOCRoot grid">
<div class="row">
<div class="col-12 col-xs-6 col-md-3">
<div class="Group"> General </div>
<div class="Item">
<a href="#devexpress-accessibility"><span>Accessibility</span></a>
</div>
<div class="Item">
<a href="#devexpress-dateonly-timeonly-support"><span>DateOnly/TimeOnly Support</span></a>
</div>
<div class="Item">
<a href="#system-text-json-support"><span>System.Text.Json Support</span></a>
</div>
<div class="Item">
<a href="#nuget"><span>NuGet</span></a>
</div>
</div>
<div class="col-12 col-xs-6 col-md-3">
<div class="Group"> Windows Desktop Controls </div>
<div class="Item">
<a href="#winforms"><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 36 36" style="enable-background:new 0 0 36 36;" xml:space="preserve" width="36px" height="36px"><title xmlns=""></title>
<style type="text/css">
.icon_blue{fill:#26A4DD;}
</style>
<path class="icon icon_blue" d="M33.3,0H2.7C1.2,0,0,1.2,0,2.7v30.6C0,34.8,1.2,36,2.7,36h30.6c1.5,0,2.7-1.2,2.7-2.7V2.7
C36,1.2,34.8,0,33.3,0z M14.4,25.2h-1.6l-1.1-6.5c0,0,0-0.1,0-0.3c0-0.2-0.1-0.5-0.1-0.8L11.4,16c0-0.1,0-0.3-0.1-0.5
s-0.1-0.5-0.1-0.9l0-0.6c0,0.1,0,0.3,0,0.4c0,0.1,0,0.2,0,0.3c0,0.4-0.1,0.8-0.1,1c0,0.2,0,0.4,0,0.4l-0.2,1.4
c0,0.3-0.1,0.6-0.1,0.8c0,0.2,0,0.3-0.1,0.4l-1.1,6.5H7.9L5.2,10.1h2l1,7l0.2,1c0.1,0.6,0.1,1.1,0.2,1.5L8.7,21c0,0,0,0.1,0,0.2
c0,0.1,0,0.2,0,0.3l0-0.5c0.1-0.9,0.2-1.6,0.2-2.4c0.1-0.7,0.2-1.4,0.3-2l1.1-6.5H12l1,6.3c0.1,0.9,0.3,1.8,0.4,2.6
c0.1,0.8,0.2,1.6,0.2,2.3c0.1-0.8,0.1-1.5,0.2-2.2c0.1-0.7,0.2-1.4,0.3-2.1l0.1-1l0.9-5.9H17L14.4,25.2z M20.3,25.2h-2V10.1h2V25.2z
M29.6,25.2h-1.9l-2.3-6.8c-0.2-0.6-0.4-1.3-0.6-1.9c-0.2-0.7-0.4-1.4-0.5-2.1c0-0.1,0-0.2-0.1-0.3c0-0.1-0.1-0.3-0.1-0.4
c0,0.2,0,0.3,0,0.4c0,0.1,0,0.2,0,0.3l0.1,1.5l0.1,1.9c0,0.1,0,0.2,0,0.4c0,0.1,0,0.3,0,0.5l0.1,6.6h-2V10.1h1.9l2,6
c0.6,1.7,1.1,3.5,1.6,5.4c-0.2-1.2-0.3-2.2-0.4-3.2c-0.1-0.9-0.1-1.8-0.1-2.7v-5.6h2V25.2z"></path>
</svg><span>WinForms</span></a>
</div>
<div class="Item">
<a href="#wpf"><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 36 36" style="enable-background:new 0 0 36 36;" xml:space="preserve" width="36px" height="36px"><title xmlns=""></title>
<style type="text/css">
.icon_blue{fill:#26A4DD;}
</style>
<path class="icon icon_blue" d="M19.9,11.8h-0.3v4.9c0.8,0,1.4-0.2,1.7-0.5c0.3-0.3,0.5-1,0.5-1.8c0-0.9-0.2-1.6-0.5-2
C21.1,12,20.6,11.8,19.9,11.8z"></path>
<path class="icon icon_blue" d="M33.3,0H2.7C1.2,0,0,1.2,0,2.7v30.6C0,34.8,1.2,36,2.7,36h30.6c1.5,0,2.7-1.2,2.7-2.7V2.7
C36,1.2,34.8,0,33.3,0z M13.8,25.2h-1.6l-1.1-6.5c0,0,0-0.1,0-0.3c0-0.2-0.1-0.5-0.1-0.8L10.8,16c0-0.1,0-0.3-0.1-0.5
c0-0.2-0.1-0.5-0.1-0.9l0-0.6c0,0.1,0,0.3,0,0.4c0,0.1,0,0.2,0,0.3c0,0.4-0.1,0.8-0.1,1c0,0.2,0,0.4,0,0.4l-0.2,1.4
c0,0.3-0.1,0.6-0.1,0.8c0,0.2,0,0.3-0.1,0.4l-1.1,6.5H7.2L4.6,10.1h2l1,7l0.2,1c0.1,0.6,0.1,1.1,0.2,1.5L8.1,21c0,0,0,0.1,0,0.2
c0,0.1,0,0.2,0,0.3l0-0.5c0.1-0.9,0.2-1.6,0.2-2.4c0.1-0.7,0.2-1.4,0.3-2l1.1-6.5h1.6l1,6.3c0.1,0.9,0.3,1.8,0.4,2.6
c0.1,0.8,0.2,1.6,0.2,2.3c0.1-0.8,0.1-1.5,0.2-2.2c0.1-0.7,0.2-1.4,0.3-2.1l0.1-1l0.9-5.9h1.9L13.8,25.2z M22.2,18.1
c-0.6,0.3-1.4,0.4-2.6,0.4v6.7h-2V10.1h2.7c1.3,0,2.2,0.3,2.8,1c0.6,0.7,0.9,1.7,0.9,3.1C24,16.2,23.4,17.5,22.2,18.1z M31,11.8
h-3.4v4.8h3.1v1.7h-3.1v6.9h-2V10.1H31V11.8z"></path>
</svg><span>WPF</span></a>
</div>
<div class="Item">
<a href="#vcl"><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 36 36" style="enable-background:new 0 0 36 36;" xml:space="preserve" width="36px" height="36px"><title xmlns=""></title>
<style type="text/css">
.icon_blue{fill:#26A4DD;}
</style>
<path class="icon icon_blue" d="M33.3,0H2.7C1.2,0,0,1.2,0,2.7v30.6C0,34.8,1.2,36,2.7,36h30.6c1.5,0,2.7-1.2,2.7-2.7V2.7
C36,1.2,34.8,0,33.3,0z M11.7,25.2h-1.6L7.2,10.1h2l0.9,5.6l0.2,1l0.3,2.2c0.1,0.4,0.1,0.7,0.1,1c0,0.3,0.1,0.6,0.1,0.8l0.1,0.7
c0-0.1,0-0.3,0-0.4c0-0.1,0-0.2,0-0.3l0.3-1.7l0.3-2.3c0-0.2,0.1-0.4,0.1-0.6s0.1-0.3,0.1-0.5l1-5.6h1.9L11.7,25.2z M21.6,12.2
c-0.5-0.3-1-0.4-1.3-0.4c-0.5,0-0.9,0.1-1.2,0.4c-0.3,0.2-0.6,0.6-0.9,1.1c-0.2,0.5-0.4,1.1-0.5,1.9c-0.1,0.8-0.2,1.7-0.2,2.7
c0,3.7,1,5.6,2.9,5.6c0.3,0,0.7-0.1,1.2-0.3V25c-0.5,0.3-1,0.4-1.6,0.4c-3.1,0-4.6-2.5-4.6-7.5c0-2.7,0.4-4.7,1.1-6
c0.7-1.3,1.9-2,3.4-2c0.6,0,1.1,0.1,1.7,0.4V12.2z M28.7,25.2h-5.4V10.1h2v13.4h3.3V25.2z"></path>
</svg><span>VCL</span></a>
</div>
<div class="Group"> Web Controls </div>
<div class="Item">
<a href="#devextreme"><svg width="36px" height="36px" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg"><title xmlns=""></title><g clip-path="url(#clip0_1311_1312)"><rect width="36" height="36" rx="3" fill="white"></rect><path fill-rule="evenodd" clip-rule="evenodd" d="M2.808 0C1.26 0 0 1.25969 0 2.8073V21.1717C6.372 14.5314 17.64 7.76506 34.614 5.38965C35.244 5.29968 35.694 5.23669 36 5.18271V2.8073C36 1.25069 34.74 0 33.192 0L2.808 0Z" fill="#26A4DD"></path><path fill-rule="evenodd" clip-rule="evenodd" d="M33.183 36H2.808V35.991C1.269 35.991 0.018 34.7493 0 33.2107C0.009 32.7968 0.279 32.113 0.414 31.843C0.828 31.0153 1.521 29.9085 2.493 28.8018C8.028 21.8735 18.558 12.4619 35.991 9.42065V33.1927C35.991 34.7403 34.74 36 33.183 36ZM31.248 26.0935C30.798 25.3736 30.222 24.7168 29.547 24.1409C29.079 23.727 28.728 23.4031 28.467 23.1422C27.036 21.7115 27.702 20.6498 28.008 20.3529C28.143 20.2179 28.314 20.1009 28.512 20.029C28.71 19.957 28.917 19.921 29.133 19.921C29.709 19.948 30.249 20.1369 30.699 20.4519L31.05 20.7038V18.3824L30.924 18.3194C30.276 18.0225 29.547 17.8605 28.827 17.8605H28.8C28.323 17.8425 27.819 17.9145 27.369 18.0855C26.919 18.2564 26.505 18.5083 26.172 18.8413C23.652 21.3606 26.19 24.078 26.469 24.3479C26.766 24.6538 27.162 25.0227 27.738 25.5356C28.053 25.8145 28.323 26.0755 28.539 26.3094C28.71 26.4984 28.872 26.6963 29.007 26.9033C29.232 27.2632 29.34 27.6771 29.331 28.0999C29.358 28.5138 29.214 28.9187 28.926 29.2337C28.791 29.3686 28.62 29.4766 28.431 29.5486C28.242 29.6206 28.026 29.6476 27.819 29.6476C27.144 29.6026 26.514 29.3866 26.001 28.9997L25.641 28.7388V31.0422L25.74 31.1052C26.379 31.5461 27.171 31.789 27.972 31.789H28.134C28.593 31.789 29.061 31.6991 29.493 31.5371C29.952 31.3571 30.357 31.0962 30.699 30.7543C31.401 30.0075 31.77 29.0537 31.734 28.091C31.761 27.3981 31.599 26.7053 31.257 26.0755L31.248 26.0935ZM22.869 18.0585H20.421V28.262C20.421 28.7569 20.331 29.6836 19.341 29.6836C18.9 29.6386 18.477 29.5037 18.117 29.2787L17.775 29.0718V31.3842L17.91 31.4472C18.432 31.6811 19.008 31.8071 19.584 31.8071H19.683C19.728 31.8071 19.7708 31.8094 19.8135 31.8116C19.8563 31.8139 19.899 31.8161 19.944 31.8161C20.367 31.8161 20.781 31.7351 21.159 31.5822C21.627 31.3932 22.869 30.8353 22.869 28.361V18.0585Z" fill="#26A4DD"></path></g><defs><clipPath id="clip0_1311_1312"><rect width="36" height="36" rx="3" fill="white"></rect></clipPath></defs></svg><span>JavaScript & ASP.NET Core</span></a>
</div>
<div class="Item">
<a href="#blazor"><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 36 36" style="enable-background:new 0 0 36 36;" xml:space="preserve" width="36px" height="36px"><title xmlns=""></title>
<style type="text/css">
.icon_blue {
fill: #26A4DD;
}
</style>
<path class="icon icon_blue" d="M11.1,16.1c-0.3,0.4-0.9,0.5-1.6,0.5v-5c0,0,0,0,0.1,0h0.1h0.2c1.2,0,1.8,0.8,1.8,2.5
C11.6,15.1,11.4,15.8,11.1,16.1z M36,2.7v30.6c0,1.5-1.2,2.7-2.7,2.7H2.7C1.2,36,0,34.8,0,33.3V2.7C0,1.2,1.2,0,2.7,0h30.6
C34.8,0,36,1.2,36,2.7z M13.8,21c0-1-0.2-1.8-0.5-2.3c-0.3-0.5-0.9-0.9-1.7-1.3c0.7-0.3,1.2-0.6,1.5-1.1c0.3-0.5,0.4-1.3,0.4-2.3
c0-2.7-1.1-4-3.2-4H7.6v15.1h2.7C12.6,25.2,13.8,23.8,13.8,21z M20.4,23.4H17V10h-2v15.1h5.4V23.4z M23.9,23.4L28.4,10h-6.7v1.7h4.1
l-4.6,13.4h7v-1.8H23.9z M9.5,18.3v5.1c0.8,0,1.4-0.2,1.7-0.5c0.3-0.4,0.5-1,0.5-2c0-1-0.2-1.6-0.5-2C10.9,18.5,10.3,18.3,9.5,18.3z"></path>
</svg><span>Blazor</span></a>
</div>
</div>
<div class="column-break sm">
</div>
<div class="column-break xsm">
</div>
<div class="column-break xs">
</div>
<div class="col-12 col-xs-6 col-md-3">
<div class="Group"> Enterprise & Server Tools </div>
<div class="Item">
<a href="#reporting"><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 36 36" style="enable-background:new 0 0 36 36;" xml:space="preserve" width="36px" height="36px"><title xmlns=""></title>
<style type="text/css">
.icon_blue{fill:#26A4DD;}
</style>
<rect x="25.1" y="20.6" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -6.3553 26.6569)" class="icon icon_blue" width="7.8" height="0.7"></rect>
<path class="icon icon_blue" d="M18,15c-3,0-5.5,1.1-5.5,2.5v3c0,1.4,2.5,2.5,5.5,2.5s5.5-1.1,5.5-2.5v-3C23.5,16.1,21,15,18,15z M18,19.5
c-2.8,0-5-0.9-5-2s2.2-2,5-2c0.5,0,1,0,1.4,0.1l-1.9,1.9H23C23,18.6,20.8,19.5,18,19.5z"></path>
<rect x="24.1" y="19.6" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -5.9411 25.6569)" class="icon icon_blue" width="7.8" height="0.7"></rect>
<path class="icon icon_blue" d="M33.3,0H2.7C1.2,0,0,1.2,0,2.7v30.6C0,34.8,1.2,36,2.7,36h30.6c1.5,0,2.7-1.2,2.7-2.7V2.7
C36,1.2,34.8,0,33.3,0z M22.5,8l4,4h-4V8z M26.5,25H25l-1-1v2h2.5v1.5c0,0.3-0.2,0.5-0.5,0.5H10c-0.3,0-0.5-0.2-0.5-0.5v-19
C9.5,8.2,9.7,8,10,8h12v4.5h4.5V20l4.5-4.5l2.5,2.5L26.5,25z"></path>
</svg><span>Reporting</span></a>
</div>
<div class="Item">
<a href="#dashboard"><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 36 36" style="enable-background:new 0 0 36 36;" xml:space="preserve" width="36px" height="36px"><title xmlns=""></title>
<style type="text/css">
.icon_blue{fill:#26A4DD;}
</style>
<path class="icon icon_blue" d="M33.3,0H2.7C1.2,0,0,1.2,0,2.7v30.6C0,34.8,1.2,36,2.7,36h30.6c1.5,0,2.7-1.2,2.7-2.7V2.7
C36,1.2,34.8,0,33.3,0z M12.5,30C8.9,30,6,27.1,6,23.5S8.9,17,12.5,17s6.5,2.9,6.5,6.5S16.1,30,12.5,30z M19.5,27
c-0.1,0-0.2,0-0.4,0c0.5-1,0.9-2.2,0.9-3.5c0-4.1-3.4-7.5-7.5-7.5c-1.1,0-2.1,0.2-3,0.6c0.2-5.3,4.6-9.6,10-9.6c2.6,0,5,1,6.8,2.7
L19,17h10.5C29.5,22.5,25,27,19.5,27z M21.5,16l7.3-7.3c2,1.8,3.2,4.4,3.2,7.3H21.5z"></path>
<path class="icon icon_blue" d="M12.5,19C10,19,8,21,8,23.5c0,0.5,0.1,1,0.3,1.5h3.2l3.5-4l-1.5,4h3.2c0.2-0.5,0.3-1,0.3-1.5
C17,21,15,19,12.5,19z"></path>
</svg><span>Business Intelligence Dashboard</span></a>
</div>
<div class="Item">
<a href="#officefileapi"><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 36 36" style="enable-background:new 0 0 36 36;" xml:space="preserve" width="36px" height="36px"><title xmlns=""></title>
<style type="text/css">
.icon_blue{fill:#26A4DD;}
</style>
<rect x="13.5" y="19" class="icon icon_blue" width="9" height="0.5"></rect>
<rect x="13.5" y="16" class="icon icon_blue" width="9" height="0.5"></rect>
<rect x="13.5" y="17" class="icon icon_blue" width="9" height="0.5"></rect>
<path class="icon icon_blue" d="M33.3,0H2.7C1.2,0,0,1.2,0,2.7v30.6C0,34.8,1.2,36,2.7,36h30.6c1.5,0,2.7-1.2,2.7-2.7V2.7
C36,1.2,34.8,0,33.3,0z M26.5,27.5c0,0.3-0.2,0.5-0.5,0.5H10c-0.3,0-0.5-0.2-0.5-0.5v-19C9.5,8.2,9.7,8,10,8h11.5v5h5V27.5z
M27.5,26.5c0,0.3-0.2,0.5-0.5,0.5V12.5l-5-5H10.5C10.5,7.2,10.7,7,11,7h16c0.3,0,0.5,0.2,0.5,0.5V26.5z M28.5,25.5
c0,0.3-0.2,0.5-0.5,0.5V7c0-0.3-0.2-0.5-0.5-0.5h-16C11.5,6.2,11.7,6,12,6h16c0.3,0,0.5,0.2,0.5,0.5V25.5z"></path>
<rect x="13.5" y="18" class="icon icon_blue" width="9" height="0.5"></rect>
<rect x="13.5" y="20" class="icon icon_blue" width="9" height="0.5"></rect>
</svg><span>Office File API</span></a>
</div>
<div class="Group"> Mobile Components </div>
<div class="Item">
<a href="#maui"><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 36 36" style="enable-background:new 0 0 36 36;" xml:space="preserve" width="36px" height="36px"><title xmlns=""></title>
<style type="text/css">
.icon_blue{fill:#26A4DD;}
</style>
<path class="icon_blue" d="M17.5,13c0.3,2.7,0.7,5.1,1.2,7.6h-2.4C16.8,18.1,17.3,15.5,17.5,13z M36,2.7v30.6c0,1.5-1.2,2.7-2.7,2.7H2.7
C1.2,36,0,34.8,0,33.3V2.7C0,1.2,1.2,0,2.7,0h30.6C34.8,0,36,1.2,36,2.7z M13,25.1l-1.4-15H9.8c-0.6,3-1.6,7.9-2,10.8
c-0.3-3-1.5-7.8-2.1-10.8H4l-1.2,15h1.9l0.6-10.4c0.3,2.9,1.4,7.4,2,10.4h1.4c0.5-2.6,1.6-7.8,1.9-10.4c0.1,3,0.3,7.3,0.5,10.4H13z
M21.6,25.1l-3.2-15h-1.6l-3.3,15h1.9l0.6-2.9h3l0.6,2.9H21.6z M29.2,10.1h-2c0,0,0,10.9,0,10.9c-0.1,1.6,0.1,2.3-1.5,2.4
c-1.6-0.1-1.4-1-1.5-2.7V10.1h-2c0,0,0,10.6,0,10.6c0,3,0.5,4.5,3.4,4.6c2.8-0.1,3.5-1.3,3.5-4.3V10.1z M32.5,10.1h-2v15h2V10.1z"></path>
</svg><span>.NET MAUI (FREE)</span></a>
</div>
</div>
<div class="col-12 col-xs-6 col-md-3">
<div class="Group"> Frameworks & Productivity </div>
<div class="Item">
<a href="#xaf"><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 36 36" style="enable-background:new 0 0 36 36;" xml:space="preserve" width="36px" height="36px"><title xmlns=""></title>
<style type="text/css">
.icon_blue{fill:#26A4DD;}
</style>
<path class="icon icon_blue" d="M18.3,13.1c-0.1,0.9-0.2,1.8-0.4,2.7c-0.1,0.9-0.3,1.9-0.5,3L17,20.7h2.4L19,18.3
C18.7,16.7,18.4,14.9,18.3,13.1z"></path>
<path class="icon icon_blue" d="M33.3,0H2.7C1.2,0,0,1.2,0,2.7v30.6C0,34.8,1.2,36,2.7,36h30.6c1.5,0,2.7-1.2,2.7-2.7V2.7
C36,1.2,34.8,0,33.3,0z M20.3,25.2l-0.6-2.9h-3l-0.6,2.9h-1.9h0h-2l-1-2.9c-0.2-0.6-0.4-1.1-0.5-1.5c-0.1-0.5-0.2-0.9-0.3-1.2
c-0.1,0.4-0.1,0.9-0.3,1.2l-0.3,1.1l-0.2,0.6l-0.9,2.7H6.6l2.9-7.7l-2.7-7.4h2l1,2.9c0.4,1.2,0.7,2,0.7,2.5c0.1-0.3,0.2-0.7,0.2-1
s0.2-0.6,0.3-0.9l0.1-0.4l1-3.1h2.1l-2.8,7.4l2.8,7.6l3.3-15h1.6l3.2,15.1H20.3z M28.9,11.8h-3.4v4.8h3.1v1.7h-3.1v6.9h-2V10.1h5.4
V11.8z"></path>
</svg><span>XAF - Cross-Platform .NET App UI</span></a>
</div>
<div class="Item">
<a href="#xaf-webapi"><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 36 36" style="enable-background:new 0 0 36 36;" xml:space="preserve" width="36px" height="36px"><title xmlns=""></title>
<style type="text/css">
.icon_blue{fill:#26A4DD;}
</style>
<path class="icon icon_blue" d="M33.3,0H2.7C1.2,0,0,1.2,0,2.7v30.6C0,34.8,1.2,36,2.7,36h30.6c1.5,0,2.7-1.2,2.7-2.7V2.7C36,1.2,34.8,0,33.3,0
z M29.9,18.4c-0.8,5.9-4.5,10-10,13l-1.9,1l-1.9-1c-5.5-3-9.1-7.2-10-13c-0.2-1.3-0.2-2.7-0.1-4l0.5-5.1c3.2,0,4.9-1.6,5.4-4.8h12
c0.6,3.2,2.2,4.8,5.4,4.8l0.5,5.1C30,15.8,30,17.1,29.9,18.4z M27.6,11.1c-2.1-0.5-4.2-1.7-5.3-4.6h-8.7c-1.1,2.9-3.2,4.2-5.3,4.6
l-0.3,3.3C8,15.8,8,17,8.1,18c0.7,4.9,3.7,8.6,9.1,11.6L18,30l0.8-0.4c5.4-2.9,8.4-6.7,9.1-11.6c0.2-1.1,0.2-2.2,0-3.6L27.6,11.1z
M25.9,17.7c-0.6,4.1-3.1,7.2-7.8,9.7L18,27.5v-19h3.2c0.9,2,2.5,3.3,4.5,4l0.2,2.2C26,15.9,26,16.8,25.9,17.7z"></path>
</svg><span>.NET App Security & Web API (FREE)</span></a>
</div>
<div class="Item">
<a href="#coderush"><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 36 36" style="enable-background:new 0 0 36 36;" xml:space="preserve" width="36px" height="36px"><title xmlns=""></title>
<style type="text/css">
.icon_blue{fill:#26A4DD;}
</style>
<path class="icon_blue" d="M21.5,12l3.5,6l-3.5,6h-7L11,18l3.5-6H21.5z M36,2.7v30.6c0,1.5-1.2,2.7-2.7,2.7H2.7
C1.2,36,0,34.8,0,33.3V2.7C0,1.2,1.2,0,2.7,0h30.6C34.8,0,36,1.2,36,2.7z M31,18c0-7.2-5.8-13-13-13C10.8,5,5,10.8,5,18
s5.8,13,13,13C25.2,31,31,25.2,31,18z"></path>
</svg><span>CodeRush (FREE)</span></a>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<section class="White">
<div class="content">
<div id="ctl00_ctl00_Content_Content_AutoTOC" class="AutoTOC">
<div id="ctl00_ctl00_Content_Content_Content">
<h2 class="SectionHeader" data-anchor="general" data-toc-title="General">
<a data-whatsnew-platform="general" name="general" class="anchor"></a>Cross-Platform Enhancements v24.1
</h2>
<h3 data-anchor="devexpress-accessibility" data-toc-title="Accessibility Enhancements">
<a name="devexpress-accessibility" class="anchor"></a>Accessibility Enhancements
</h3>
<p> Accessibility support remains a top engineering priority. Accordingly, we enhanced keyboard navigation/screen reader support, extended automation capabilities and other accessibility-related features to ensure better compliance with
standards outlined in WCAG. </p>
<p> This release includes enhancements across most of our desktop and web component suites: </p>
<ul>
<li><a href="#winforms-accessibility">WinForms Controls</a></li>
<li><a href="#wpf-accessibility">WPF Controls</a></li>
<li><a href="#js-accessibility">DevExtreme JavaScript Components</a></li>
<li><a href="#blazor-keyboard-support">Blazor UI Components</a></li>
<li><a href="#aspnetcore">ASP.NET Core Controls</a></li>
<li><a href="#reporting-accessibility">.NET Reporting</a></li>
<li><a href="#xaf-blazor-accessibility">XAF - Cross-Platform .NET App UI (Blazor)</a></li>
<li><a href="#vcl-accessibility">VCL Controls</a></li>
</ul> <span class="H-Separator"></span>
<h3 data-anchor="devexpress-dateonly-timeonly-support" data-toc-title="Support of New .NET DateOnly and TimeOnly Types Across UI Platforms">
<a name="devexpress-dateonly-timeonly-support" class="anchor"></a>Support of New .NET DateOnly and TimeOnly Types Across UI Platforms
</h3>
<p> We now support <code data-renderer="hljs" class="csharp" data-control="Code-Inline">DateOnly</code> and <code data-renderer="hljs" class="csharp" data-control="Code-Inline">TimeOnly</code> types in data-aware UI controls (such as Data
Grid, Tree List, Date and Time Editors) for the following UI platforms in .NET Core / .NET 6+ apps. </p>
<ul>
<li><a href="#winforms-dateonly-support">WinForms Controls</a></li>
<li><a href="#wpf-dateonly-support">WPF Controls</a></li>
<li><a href="#blazor-grid-dateonly-timeonly-support">Blazor UI Components</a></li>
<li><a href="#xaf-dateonly-timeonly-support">XAF - Cross-Platform .NET App UI (Blazor)</a></li>
</ul>
<p><span class="FootNote"> * Please review the links above for additional information (supported features vary across UI platforms and controls). </span></p>
<p> Thanks to changes at core levels (our DevExpress.Data and DevExtreme.AspNet.Data libraries), we now support these data types for our client/in-memory and server mode data sources (both of which are used by multiple UI controls listed
above): </p>
<ul>
<li>EntityServerModeSource / EntityInstantFeedbackSource</li>
<li>LinqServerModeSource / LinqInstantFeedbackSource</li>
<li>GridDevExtremeDataSource (for ASP.NET Core / DevExtreme and Blazor-based controls)</li>
</ul>
<p> You can sort, group, and filter data (and other capabilities) against DateOnly and TimeOnly values. We also extended our
<a href="https://docs.devexpress.com/CoreLibraries/4928/devexpress-data-library/criteria-language-syntax?v=24.1" target="_blank" rel="noopener">criteria language</a> as follows: </p>
<ul>
<li>
<p> You can use date/time-related functions (such as AddHours, GetDays, DateDiffDays, etc.) in filter expressions and unbound columns. </p>
</li>
<li>
<p> You can now wrap DateOnly/TimeOnly constants in '#' and '!' for string filter expressions: </p>
<p><code data-renderer="hljs" class="csharp" data-control="Code-Inline">[<span class="hljs-meta">OrderDate</span>] >= <span class="hljs-meta">#!2018-03-22!# && [OrderTime] >= #!18:22:00!#</span></code></p>
</li>
</ul>
<p> Due to the following Microsoft-related breaking change these new data types are of special importance to EF Core 8 developers:
<a href="https://learn.microsoft.com/en-us/ef/core/what-is-new/ef-core-8.0/breaking-changes#sqlserver-date-time-only" target="_blank" rel="noopener">SQL Server date and time now scaffold to .NET DateOnly and TimeOnly</a>. DevExpress
customers will benefit from this new functionality even if NOT using EF Core 8 for data access – it is just important that the underlying database or IQueryable provider supports the new data types (like Microsoft SQL Server with EF
Core 8). Here is a quote from Microsoft about the general value for .NET developers: </p>
<div class="Attention">
<p><a href="https://learn.microsoft.com/en-us/dotnet/api/system.dateonly" target="_blank" rel="noopener">DateOnly</a> and <a href="https://learn.microsoft.com/en-us/dotnet/api/system.timeonly" target="_blank" rel="noopener">TimeOnly</a>
were introduced in .NET 6.0, and are a perfect match for mapping the database date and time types. <code data-renderer="hljs" class="csharp" data-control="Code-Inline">DateTime</code> notably contains a time component that goes unused
and can cause confusion when mapping it to date, and <code data-renderer="hljs" class="csharp" data-control="Code-Inline">TimeSpan</code> represents a time interval - possibly including days - rather than a time of day at which an
event occurs. Using the new types prevents bugs and confusion, and provides clarity of intent. </p>
</div>
<p><strong>Note</strong>: Microsoft and third-party package vendors did not backport DateOnly and TimeOnly types on .NET Framework. Additionally, we do not officially support this feature for .NET Framework and OData/XPO data sources
within both frameworks. We encourage you to migrate to .NET 6+ to benefit from the new data types. Technically, we share parts of our codebase between .NET Framework and .NET, so do not be confused that our DevExpress.Data library for
.NET Framework includes our own "shim" DateOnly and TimeOnly types. If you experience any conflicts with third-party compatibility packages (like one or two for unofficial support), we recommend that you remove these packages. </p>
<span class="H-Separator"></span>
<h3 data-anchor="system-text-json-support" data-toc-title=".NET and .NET Framework — Migration from Newtonsoft.Json to System.Text.Json">
<a name="system-text-json-support" class="anchor"></a>.NET and .NET Framework — Migration from Newtonsoft.Json to System.Text.Json
</h3>
<p> In our v24.1 release cycle, the following DevExpress products will use Microsoft’s System.Text.Json instead of Newtonsoft.Json for JSON serialization-related tasks in <strong>runtime code</strong>: </p>
<ul>
<li>
<p> Data Access Library: BI Dashboards (DashboardJsonDataSource) and Reporting (JsonDataSource) for .NET 6+ WinForms, WPF, Blazor, ASP.NET Core apps (.NET Framework apps will continue to use the Newtonsoft.Json library. We expect to
switch to System.Text.Json in our v24.2 release cycle).
<br><a href="https://supportcenter.devexpress.com/ticket/details/t1224045/system-text-json-is-used-to-process-the-jsondatasource-dashboardjsondatasource-component" target="_blank" rel="noopener">Breaking Change</a></p>
</li>
<li>
<p> Data Access Library for .NET 6+ and .NET Framework DevExtreme, Blazor and ASP.NET Core apps (a System.Text.Json-compatible version of
<a href="https://www.nuget.org/packages/DevExtreme.AspNet.Data/4.0.0-beta" target="_blank" rel="noopener">DevExtreme.AspNet.Data v4.0.0+</a> is now available).
<br><a href="https://supportcenter.devexpress.com/ticket/details/t1227758/devextreme-devextreme-aspnet-data-processing-and-serialization-now-use-system-text-json" target="_blank" rel="noopener">Breaking Change</a></p>
</li>
<li>
<p> Backend Web API Service for .NET 6+ non-XAF apps (DevExtreme, Blazor, .NET MAUI, etc.) and XAF apps.
<br><a href="https://supportcenter.devexpress.com/ticket/details/t1225165/xaf-system-text-json-library-is-used-to-deserialize-input-parameters-of-the-web-api" target="_blank" rel="noopener">Breaking Change</a></p>
</li>
<li>
<p> Maps in .NET 6+ WinForms in WPF, Blazor, ASP.NET Core apps (.NET Framework apps will continue to use the Newtonsoft.Json library. We expect to switch to System.Text.Json in our v24.2 release cycle).
<br><a href="https://supportcenter.devexpress.com/ticket/details/t1225036/system-text-json-is-used-to-process-the-vector-tile-styles-instead-of-the-newtonsoft" target="_blank" rel="noopener">Breaking Change</a></p>
</li>
<li>Blazor Rich Text Editor (no Breaking Changes).</li>
</ul>
<p> Our design-time code (wizards, designers and tools) may still continue to use Newtonsoft.Json, because of dependencies within Visual Studio (some design-time services still rely on Newtonsoft.Json, but we believe this will change in
the future). Remaining .NET Framework products that currently rely on the Newtonsoft.Json library, will likely switch to System.Text.Json in the future. Here we rely on the
<a href="https://learn.microsoft.com/en-us/lifecycle/products/microsoft-net-framework" target="_blank" rel="noopener">minimally supported .NET Framework version</a> for DevExpress products, which will likely change from 4.5.2 to 4.6.2
in v24.2. </p> <span class="H-Separator"></span>
<h3 data-anchor="nuget" data-toc-title="Regenerate Your NuGet API Key (Feed)">
<a name="nuget" class="anchor"></a>Regenerate Your NuGet API Key (Feed)
</h3>
<p> To regenerate the NuGet API key, navigate to <a href="https://nuget.devexpress.com/#feed-url" target="_blank" rel="noopener">https://nuget.devexpress.com/</a> and click the Regenerate Feed link. </p>
<p> Your NuGet API key is sensitive information, and you should protect it from unauthorized use by untrusted third parties. If you have leaked your NuGet API key, you need to regenerate it as soon as possible. Cases or reasons to
regenerate a NuGet API key may include, but are not limited to, the following: </p>
<ul>
<li>You included your NuGet API key in a public forum post, GitHub repository, log files, or other authorized place by mistake.</li>
<li>Members of your team who previously had access to your NuGet Feed have left the company.</li>
<li>You know or suspect that your NuGet API key has been stolen or compromised.</li>
</ul> <p><img src="/subscriptions/i/24.1/regenerate-nuget-api-key.png" srcset="/subscriptions/i/24.1/regenerate-nuget-api-key.png 1x, /subscriptions/i/24.1/regenerate-nuget-api-key@2x.png 2x"
alt="Regenerate Your NuGet API Key (Feed)" width="950" height="204" style="border: none" id="ctl00_ctl00_Content_Content_ctl273"></p> <span class="H-Separator"></span>
<h3 data-anchor="nuget-docs" data-toc-title="DevExpress NuGet Server - Enhanced Documentation">
<a name="nuget-docs" class="anchor"></a>DevExpress NuGet Server - Enhanced Documentation
</h3>
<h4 anchor="">
</h4>
<p> We updated our online documentation to address popular usage scenarios based on user feedback. We clarified which DevExpress NuGet feed (offline or online) to use for Windows, Mac OS, Linux: </p>
<ul>
<li><a href="https://docs.devexpress.com/GeneralInformation/116042/nuget/obtain-your-nuget-feed-credentials" target="_blank" rel="noopener">Choose Between Offline and Online DevExpress NuGet Feeds</a></li>
<li><a href="https://docs.devexpress.com/GeneralInformation/116698/nuget/setup-visual-studios-nuget-package-manager?v=24.1" target="_blank" rel="noopener">Install NuGet Packages in Visual Studio, VS Code, and Rider</a></li>
<li><a href="https://docs.devexpress.com/GeneralInformation/400604/nuget/integrate-nuget-to-popular-continuous-integration-systems?v=24.1#gitlab" target="_blank" rel="noopener">Integration with GitLab</a></li>
<li>
<a href="https://docs.devexpress.com/GeneralInformation/404166/nuget/security-licensing-reliability-considerations?v=24.1#how-to-protect-your-private-nuget-feed-and-safely-consume-the-feed-from-external-systems" target="_blank" rel="noopener">Security Best Practices for other CI/CD Systems</a>
</li>
</ul> <span class="H-Separator"></span>
<h2 class="SectionHeader" data-anchor="winforms" data-toc-title="WinForms">
<a data-whatsnew-platform="winforms" name="winforms" class="anchor"></a>WinForms Controls v24.1
</h2>
<div class="WhatsNewTOC grid sys-visibility-hidden sys-visibility-hidden sys-visibility-sm-shown">
<div class="row">
<div class="col-sm-6 col-md-3 col-order-1">
<p><a href="#winforms-dateonly-support"><span>DateOnly & TimeOnly Type Support</span></a></p>
<p><a href="#xtragrid"><span>Data Grid</span></a></p>
<p><a href="#xtratreelist"><span>TreeList</span></a></p>
<p><a href="#xtraaccordion"><span>Accordion</span></a></p>
<p><a href="#xtraribbon"><span>Ribbon & Bars</span></a></p>
</div>
<div class="col-sm-6 col-md-3 col-sm-order-3 col-md-order-2">
<p><a href="#xtraeditors"><span>Data Editors</span></a></p>
<p><a href="#xtradocumentmanager"><span>Document Manager</span></a></p>
<p><a href="#xtradocking"><span>Docking Library</span></a></p>
<p><a href="#winforms-html-css-support"><span>HTML & CSS Support</span></a></p>
</div>
<div class="column-break sm">
</div>
<div class="col-sm-6 col-md-3 col-sm-order-2 col-md-order-3">
<p><a href="#xtrapdfviewer"><span>PDF Viewer</span></a></p>
<p><a href="#xtrarichtextedit"><span>Rich Text Editor</span></a></p>
<p><a href="#winforms-svg-scroll-cursor"><span>SVG Scroll Cursor</span></a></p>
<p><a href="#xtraspreadsheet"><span>Spreadsheet</span></a></p>
</div>
<div class="col-sm-6 col-md-3 col-order-4">
<p><a href="#winforms-accessibility"><span>Accessibility and UI Automation</span></a></p>
<p><a href="#winforms-misc"><span>Miscellaneous Enhancements</span></a></p>
<p><a href="#winforms-performance"><span>Performance Improvements</span></a></p>
<p><a href="#winforms-survey"><span>Survey - WinForms</span></a></p>
</div>
</div>
</div>
<div class="Attention">
<p><strong>Your feedback matters.</strong><br> Please, review the description of <strong>WinForms</strong>-related features below and leave your feedback at the end of the section. </p>
<p><a href="#winforms-survey">Go to the survey now.</a></p>
</div>
<h3 data-anchor="winforms-dateonly-support" data-toc-title="DateOnly & TimeOnly Type Support">
<a name="winforms-dateonly-support" class="anchor"></a>DateOnly & TimeOnly Type Support
</h3>
<p> DevExpress WinForms data-aware UI controls (such as our Data Grid and TreeList) and the Date Editor now support <code data-renderer="hljs" class="csharp" data-control="Code-Inline">DateOnly</code> and <code data-renderer="hljs"
class="csharp" data-control="Code-Inline">TimeOnly</code> data types (in .NET applications). These data types offer the following advantages (versus the traditional DateTime type): usage clarity, improved database compatibility, less
space during serialization, and the ability to mitigate potential errors/inconsistencies related to different time zones. </p>
<p> Built-in DateOnly/TimeOnly support extends to: </p>
<ul>
<li>UI Elements Related to Data Filtering (Column Filter Popup, Filter Editor, Expression Editor, Automatic Filter Row)</li>
<li>Conditional Formatting Rules</li>
<li>Data Summaries</li>
<li>Data Grouping</li>
<li>Unbound Columns</li>
<li>Masks</li>
<li>Search</li>
<li> Criteria Operators <div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">C#</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="csharp">gridView.ActiveFilterString = <span class="hljs-string">"[Date]=#!2022-02-01!#"</span>;
</code></pre>
</div>
</div>
</li>
</ul>
<p> We also added DateOnly/TimeOnly type support within our server-based data sources: </p>
<ul>
<li>EntityServerModeSource / EntityInstantFeedbackSource</li>
<li>LinqServerModeSource / LinqInstantFeedbackSource</li>
</ul>
<p> You can sort, group, and filter data in server mode sources against DateOnly and TimeOnly values. And yes, you can use date/time-related functions (such as AddHours(), GetDays(), DateDiffDays()) in filter expressions and unbound
columns. </p> <span class="H-Separator"></span>
<h3 data-anchor="xtragrid" data-toc-title="Data Grid">
<a name="xtragrid" class="anchor"></a>Data Grid
</h3>
<h4 anchor="xtragrid-merged-cell-editing">
<a name="xtragrid-merged-cell-editing" class="anchor visible-anchor" href="#xtragrid-merged-cell-editing">#</a>Merged Cell Editing
</h4>
<p> As its name implies, users can now simultaneously edit all cells in a merged range or modify separate cells (in GridView and BandedGridView) as needs dictate. Use the new
<a href="https://docs.devexpress.com/WindowsForms/DevExpress.XtraGrid.Views.Grid.GridOptionsView.MergedCellEditMode?v=24.1" target="_blank" rel="noopener">MergedCellEditMode</a> property to activate this feature and specify how users
edit merged cell data. </p>
<p><img src="/subscriptions/i/24.1/24-1-winforms-grid-edit-merged-cells.gif" srcset="/subscriptions/i/24.1/24-1-winforms-grid-edit-merged-cells.gif 1x, /subscriptions/i/24.1/24-1-winforms-grid-edit-merged-cells@2x.gif 2x"
alt="Merged Cell Editing - WinForms Data Grid, DevExpress" width="982" height="434" style="border: none" id="ctl00_ctl00_Content_Content_ctl522"></p>
<p> Options include: </p>
<ul>
<li><code data-renderer="hljs" class="csharp" data-control="Code-Inline">VisibleCells</code> – Edits data cells in a merged range. </li>
<li><code data-renderer="hljs" class="csharp" data-control="Code-Inline">FocusedCell</code> – Edits data cells in a merged range for the focused row. </li>
<li><code data-renderer="hljs" class="csharp" data-control="Code-Inline">Disabled</code></li>
</ul>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">C#</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="csharp"><span class="hljs-keyword">using</span> DevExpress.XtraGrid.Views.Grid;
<span class="hljs-comment">// Allows users to edit data cells in a merged range.</span>
gridView1.OptionsView.MergedCellEditMode = MergedCellEditMode.VisibleCells;</code></pre>
</div>
</div>
<div class="grid block-grid sys-max-width-lg-80 sys-visibility-hidden sys-visibility-hidden sys-visibility-sm-shown">
<div class="row">
<div class="col-sm-3">
<a href="dxdemo://Win/XtraGrid/MainDemo/CellMerging" target="_blank" rel="noopener" class="Button Gray">
Run Demo
</a>
</div>
<div class="col-sm-9 sys-v-align-middle">
<span class="FootNote"> To execute this demo, you must first <br><a href="https://go.devexpress.com/DevexpressDownload_UniversalTrial.aspx" target="_blank" rel="noopener">
install the DevExpress WinForms product library
</a>. </span>
</div>
</div>
</div> <span class="H-Separator"></span>
<h4 anchor="xtragrid-find-panel-customization">
<a name="xtragrid-find-panel-customization" class="anchor visible-anchor" href="#xtragrid-find-panel-customization">#</a>Display Custom UI Elements in the Find Panel
</h4>
<p> v24.1 includes new APIs to display predefined and/or custom UI controls in the Find Panel. With this new option, you can build fully customizable/personalized interfaces when using the DevExpress Find Panel. </p>
<p></p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-winforms-grid-find-panel-custom-button.png"
srcset="/subscriptions/i/24.1/24-1-winforms-grid-find-panel-custom-button.png 1x, /subscriptions/i/24.1/24-1-winforms-grid-find-panel-custom-button@2x.png 2x"
alt="Display Custom UI Elements in the Find Panel - WinForms Data Grid, DevExpress" width="809" height="417" style="border: none" id="ctl00_ctl00_Content_Content_ctl538"></div>
<p></p>
<p> Use <a href="https://docs.devexpress.com/WindowsForms/DevExpress.XtraGrid.Views.Base.ColumnView.FindPanelItems?v=24.1" target="_blank" rel="noopener">view.FilterPanelItems</a> to introduce custom Find Panel UI elements in your
WinForms app: </p>
<ul>
<li><a href="https://docs.devexpress.com/WindowsForms/DevExpress.XtraLayout.Custom.FindControlItemsCore.AddControl(System.Windows.Forms.Control)?v=24.1" target="_blank" rel="noopener">AddControl</a> — Displays the specified UI control.
</li>
<li><a href="https://docs.devexpress.com/WindowsForms/DevExpress.XtraLayout.Custom.FindControlItemsCore.AddButton.overloads?v=24.1" target="_blank" rel="noopener">AddButton</a> — Displays a button. </li>
<li><a href="https://docs.devexpress.com/WindowsForms/DevExpress.XtraLayout.Custom.FindControlItemsCore.AddCheckButton.overloads?v=24.1" target="_blank" rel="noopener">AddCheckButton</a> — Displays a checked button. </li>
<li><a href="https://docs.devexpress.com/WindowsForms/DevExpress.XtraLayout.Custom.FindControlItemsCore.AutoHeight?v=24.1" target="_blank" rel="noopener">AutoHeight</a> — Updates Find Panel height to match UI elements. </li>
<li><a href="https://docs.devexpress.com/WindowsForms/DevExpress.XtraLayout.Custom.FindControlItemsCore.RemoveItem(System.String)?v=24.1" target="_blank" rel="noopener">RemoveItem</a> /
<a href="https://docs.devexpress.com/WindowsForms/DevExpress.XtraLayout.Custom.FindControlItemsCore.RemoveItems(System.String---System.Boolean)?v=24.1" target="_blank" rel="noopener">RemoveItems</a> – Removes the specified UI
element(s) from the Find Panel. </li>
</ul> <div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">C#</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="csharp"><span class="hljs-comment">// This code snippet comes from the Find Panel module in our WinForms Data Grid demo (v24.1).</span>
CheckButton showCustomButton = <span class="hljs-literal">null</span>;
<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">ceShowCustomButton_CheckedChanged</span>(<span class="hljs-params"><span class="hljs-built_in">object</span> sender, EventArgs e</span>)</span> {
CheckEdit customButton = sender <span class="hljs-keyword">as</span> CheckEdit;
<span class="hljs-keyword">if</span>(customButton.Checked) {
showCustomButton = view.FindPanelItems.AddCheckButton(customButtonName, <span class="hljs-literal">null</span>, view.OptionsFind.Behavior != FindPanelBehavior.Search,
(button, args) => {
CheckButton checkButton = button <span class="hljs-keyword">as</span> CheckButton;
view.OptionsFind.Behavior = checkButton.Checked ? FindPanelBehavior.Filter : FindPanelBehavior.Search;
checkButton.ToolTip = <span class="hljs-string">"Find Panel Mode"</span>;
icbFindPanelBehavior.EditValue = view.OptionsFind.Behavior;
});
showCustomButton.ImageOptions.ImageUri.Uri = <span class="hljs-string">"Filter;Size16x16;Svg"</span>;
}
<span class="hljs-keyword">else</span> {
showCustomButton = <span class="hljs-literal">null</span>;
view.FindPanelItems.RemoveItem(customButtonName);
}
icbFindPanelBehavior.Enabled = showCustomButton == <span class="hljs-literal">null</span>;
}</code></pre>
</div>
</div>
<div class="grid block-grid sys-max-width-lg-80 sys-visibility-hidden sys-visibility-hidden sys-visibility-sm-shown">
<div class="row">
<div class="col-sm-3">
<a href="dxdemo://Win/XtraGrid/MainDemo/FindFilter" target="_blank" rel="noopener" class="Button Gray">
Run Demo
</a>
</div>
<div class="col-sm-9 sys-v-align-middle">
<span class="FootNote"> To execute this demo, you must first <br><a href="https://go.devexpress.com/DevexpressDownload_UniversalTrial.aspx" target="_blank" rel="noopener">
install the DevExpress WinForms product library
</a>. </span>
</div>
</div>
</div> <span class="H-Separator"></span>
<h4 anchor="xtragrid-excel-filter-customization">
<a name="xtragrid-excel-filter-customization" class="anchor visible-anchor" href="#xtragrid-excel-filter-customization">#</a>Hide Specific Filters from Excel-inspired Filter Dropdown
</h4>
<p> The WinForms Data Grid control exposes a <a href="https://docs.devexpress.com/WindowsForms/DevExpress.XtraGrid.Views.Base.ColumnView.ShowFilterPopupExcel?v=24.1" target="_blank" rel="noopener">ShowFilterPopupExcel</a> event and allows
you to hide specific filter options from "Filters" and "Values" tabs of our
<a href="https://docs.devexpress.com/WindowsForms/114635/controls-and-libraries/data-grid/filter-and-search" target="_blank" rel="noopener">Excel-style Filter Dropdown</a>. v24.1 adds a
<a href="https://docs.devexpress.com/WindowsForms/DevExpress.XtraGrid.Views.Grid.FilterPopupExcelEventArgs.HideFilter(DevExpress.Utils.Filtering.Internal.CustomUIFilterType)?v=24.1" target="_blank" rel="noopener">e.HideFilter(filterType)</a>
method to event arguments for advanced customization of the filter menu. Use this method to hide unnecessary filter operators from the "Filters" tab. </p>
<p> We also introduced this feature in our WinForms TreeList control. </p>
<p></p>
<div class="small-image"><img src="/subscriptions/i/24.1/winforms-datagrid-filterpopup-customization.png"
srcset="/subscriptions/i/24.1/winforms-datagrid-filterpopup-customization.png 1x, /subscriptions/i/24.1/winforms-datagrid-filterpopup-customization@2x.png 2x"
alt="Hide Specific Filters from Excel-inspired Filter Dropdown - WinForms Data Grid, DevExpress" width="571" height="480" style="border: none" id="ctl00_ctl00_Content_Content_ctl569"></div>
<p></p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">C#</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="csharp"><span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">gridView1_ShowFilterPopupExcel</span>(<span class="hljs-params"><span class="hljs-built_in">object</span> sender, DevExpress.XtraGrid.Views.Grid.FilterPopupExcelEventArgs e</span>)</span> {
<span class="hljs-keyword">if</span> (e.Column.FieldName == <span class="hljs-string">"UnitPrice"</span>) {
e.HideFilter(DevExpress.Utils.Filtering.Internal.CustomUIFilterType.BelowAverage);
e.HideFilter(DevExpress.Utils.Filtering.Internal.CustomUIFilterType.Between);
e.HideFilter(DevExpress.Utils.Filtering.Internal.CustomUIFilterType.BottomN);
<span class="hljs-comment">// ...</span>
}
}</code></pre>
</div>
</div> <span class="H-Separator"></span>
<h4 anchor="xtragrid-custom-popup-menu">
<a name="xtragrid-custom-popup-menu" class="anchor visible-anchor" href="#xtragrid-custom-popup-menu">#</a>Display a Custom DevExpress Popup Menu
</h4>
<p> We've made it easier to display the <a href="https://docs.devexpress.com/WindowsForms/DevExpress.XtraBars.PopupMenu?v=24.1" target="_blank" rel="noopener">DevExpress PopupMenu</a> for individual Data Grid UI elements. </p>
<p></p>
<div class="small-image"><img src="/subscriptions/i/24.1/winforms-data-grid-context-menu-devexpress.png"
srcset="/subscriptions/i/24.1/winforms-data-grid-context-menu-devexpress.png 1x, /subscriptions/i/24.1/winforms-data-grid-context-menu-devexpress@2x.png 2x" alt="Display a Custom DevExpress Popup Menu - WinForms Data Grid, DevExpress"
width="605" height="232" style="border: none" id="ctl00_ctl00_Content_Content_ctl583"></div>
<p></p>
<p> In previous versions, you had to customize the built-in menu (add/remove menu items) within the control's <code data-renderer="hljs" class="csharp" data-control="Code-Inline">PopupMenuShowing</code> event. With v24.1, you can display
a custom menu (created and customized at design time or runtime) using the new
<a href="https://docs.devexpress.com/WindowsForms/DevExpress.Utils.Menu.BasePopupMenuShowingEventArgs.ShowCustomMenu(DevExpress.Utils.Menu.IDXDropDownControlEx)?v=24.1" target="_blank" rel="noopener">e.ShowCustomMenu</a> method: </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">C#</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="csharp"><span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">gridView1_PopupMenuShowing</span>(<span class="hljs-params"><span class="hljs-built_in">object</span> sender, PopupMenuShowingEventArgs e</span>)</span> {
<span class="hljs-keyword">if</span> (e.MenuType == GridMenuType.Column) {
popupMenu_Column.Tag = e.HitInfo;
popupMenu_Column.MenuCaption = <span class="hljs-string">$"<span class="hljs-subst">{e.HitInfo.Column}</span>"</span>;
e.ShowCustomMenu(popupMenu_Column);
}
}</code></pre>
</div>
</div>
<p><strong>API enhancements extend to</strong>: DevExpress TreeList, Vertical Grid (Property Grid), and Pivot Grid. </p>
<p>
<a href="https://docs.devexpress.com/WindowsForms/10326/common-features/menus/how-to-implement-custom-menu-in-xtragrid-control?v=24.1" target="_blank" rel="noopener">How to: Implement a Custom Menu in the DevExpress WinForms Data Grid</a>
</p> <span class="H-Separator"></span>
<h4 anchor="xtragrid-export-cell-images">
<a name="xtragrid-export-cell-images" class="anchor visible-anchor" href="#xtragrid-export-cell-images">#</a>Export Cell Images to Excel
</h4>
<p> The WinForms Data Grid control now exports images (raster and SVG) displayed within cells of bound and unbound columns to XLSX in
<a href="https://docs.devexpress.com/WindowsForms/17733/controls-and-libraries/data-grid/export-and-printing/export-to-xls-and-xlsx-formats#choose-export-mode" target="_blank" rel="noopener">data-aware export mode</a>. Cell images are
exported as a Byte[] array. To activate this feature, set the <a href="https://docs.devexpress.com/CoreLibraries/DevExpress.XtraPrinting.XlsxExportOptionsEx.AllowCellImages" target="_blank" rel="noopener">AllowCellImages</a> property to
<code data-renderer="hljs" class="csharp" data-control="Code-Inline">DefaultBoolean.True</code>. </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">C#</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="csharp"><span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">btnExport_Click</span>(<span class="hljs-params"><span class="hljs-built_in">object</span> sender, EventArgs e</span>)</span> {
DevExpress.XtraPrinting.XlsxExportOptionsEx options = <span class="hljs-keyword">new</span> DevExpress.XtraPrinting.XlsxExportOptionsEx();
options.AllowCellImages = DevExpress.Utils.DefaultBoolean.True;
advBandedGridView1.ExportToXlsx(<span class="hljs-string">"grid_export.xlsx"</span>, options);
}</code></pre>
</div>
</div>
<div class="grid block-grid sys-max-width-lg-80 sys-visibility-hidden sys-visibility-hidden sys-visibility-sm-shown">
<div class="row">
<div class="col-sm-3">
<a href="dxdemo://Win/XtraGrid/MainDemo/ViewStyles" target="_blank" rel="noopener" class="Button Gray">
Run Demo
</a>
</div>
<div class="col-sm-9 sys-v-align-middle">
<span class="FootNote"> To execute this demo, you must first <br><a href="https://go.devexpress.com/DevexpressDownload_UniversalTrial.aspx" target="_blank" rel="noopener">
install the DevExpress WinForms product library
</a>. </span>
</div>
</div>
</div>
<p> You can customize cell images or replace values with images (based on export conditions) before the Grid Control generates the output document. Handle the
<a href="https://docs.devexpress.com/CoreLibraries/DevExpress.XtraPrinting.XlsxExportOptionsEx.CustomizeCell?v=24.1#replace-cell-content-with-images" target="_blank" rel="noopener">CustomizeCell</a> event as follows: </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">C#</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="csharp"><span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">Options_CustomizeCell</span>(<span class="hljs-params">DevExpress.Export.CustomizeCellEventArgs e</span>)</span> {
<span class="hljs-keyword">if</span>(e.ColumnFieldName == <span class="hljs-string">"Photo"</span> &amp;&amp; e.Value == <span class="hljs-literal">null</span>) {
e.Value = XtraEditors.Controls.ByteImageConverter.ToByteArray(imageCollection1.Images[<span class="hljs-string">"car"</span>]);
e.Handled = <span class="hljs-literal">true</span>;
}
}</code></pre>
</div>
</div>
<p></p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-winforms-grid-export-custom-cell-images.png"
srcset="/subscriptions/i/24.1/24-1-winforms-grid-export-custom-cell-images.png 1x, /subscriptions/i/24.1/24-1-winforms-grid-export-custom-cell-images@2x.png 2x"
alt="Customize Cell Images During Export to Excel - WinForms Data Grid, DevExpress" width="614" height="601" style="border: none" id="ctl00_ctl00_Content_Content_ctl625"></div>
<p></p> <span class="H-Separator"></span>
<h4 anchor="xtragrid-calc-best-size">
<a name="xtragrid-calc-best-size" class="anchor visible-anchor" href="#xtragrid-calc-best-size">#</a>Calculate the Best Size
</h4>
<p> Designed to address common layout-related dev tasks, the new
<a href="https://docs.devexpress.com/WindowsForms/DevExpress.XtraGrid.GridControl.CalcBestSize(System.Drawing.Size-System.Boolean)?v=24.1" target="_blank" rel="noopener">CalcBestSize(maxSize, checkScrollInfo)</a> method calculates the
maximum allowable size of the Grid Control (to display as many data rows and columns as possible). </p> <span class="H-Separator"></span>
<h4 anchor="xtragrid-custom-paint-tiles">
<a name="xtragrid-custom-paint-tiles" class="anchor visible-anchor" href="#xtragrid-custom-paint-tiles">#</a>Custom Tile Painting for the DevExpress TileView (Kanban)
</h4>
<p> You can now customize tile appearance by handling the new <a href="https://docs.devexpress.com/WindowsForms/DevExpress.XtraGrid.Views.Tile.TileView.CustomDrawTile?v=24.1" target="_blank" rel="noopener">TileView.CustomDrawTile</a>
event. With its comprehensive event arguments (APIs), you can easily change border shape and color or draw custom UI elements to address specific design requirements/user preferences. </p>
<p></p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-winforms-tileview-customdraw.png" srcset="/subscriptions/i/24.1/24-1-winforms-tileview-customdraw.png 1x, /subscriptions/i/24.1/24-1-winforms-tileview-customdraw@2x.png 2x"
alt="Custom Tile Painting for the DevExpress TileView - WinForms Data Grid, DevExpress" width="489" height="337" style="border: none" id="ctl00_ctl00_Content_Content_ctl649"></div>
<p></p>
<div class="grid block-grid sys-max-width-lg-80 sys-visibility-hidden sys-visibility-hidden sys-visibility-sm-shown">
<div class="row">
<div class="col-sm-3">
<a href="dxdemo://Win/XtraGrid/MainDemo/CodeExamples/TileView_Custom_painting.CustomDrawTile" target="_blank" rel="noopener" class="Button Gray">
Run Demo
</a>
</div>
<div class="col-sm-9 sys-v-align-middle">
<span class="FootNote"> To execute this demo, you must first <br><a href="https://go.devexpress.com/DevexpressDownload_UniversalTrial.aspx" target="_blank" rel="noopener">
install the DevExpress WinForms product library
</a>. </span>
</div>
</div>
</div>
<p> And yes, you can render <a href="https://docs.devexpress.com/WindowsForms/403397/common-features/html-css-based-desktop-ui?v=24.1" target="_blank" rel="noopener">HTML and CSS templates</a> inside tiles as needs dictate: </p>
<p></p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-winforms-tileview-customdraw-html-css.png"
srcset="/subscriptions/i/24.1/24-1-winforms-tileview-customdraw-html-css.png 1x, /subscriptions/i/24.1/24-1-winforms-tileview-customdraw-html-css@2x.png 2x" alt="Render HTML/CSS Templates Inside Tiles - WinForms Data Grid, DevExpress"
width="598" height="250" style="border: none" id="ctl00_ctl00_Content_Content_ctl658"></div>
<p></p>
<div class="grid block-grid sys-max-width-lg-80 sys-visibility-hidden sys-visibility-hidden sys-visibility-sm-shown">
<div class="row">
<div class="col-sm-3">
<a href="dxdemo://Win/XtraGrid/MainDemo/CodeExamples/TileView_Custom_painting.CustomDrawTile" target="_blank" rel="noopener" class="Button Gray">
Run Demo
</a>
</div>
<div class="col-sm-9 sys-v-align-middle">
<span class="FootNote"> To execute this demo, you must first <br><a href="https://go.devexpress.com/DevexpressDownload_UniversalTrial.aspx" target="_blank" rel="noopener">
install the DevExpress WinForms product library
</a>. </span>
</div>
</div>
</div> <span class="H-Separator"></span>
<h4 anchor="xtragrid-conditional-formatting-tooltip">
<a name="xtragrid-conditional-formatting-tooltip" class="anchor visible-anchor" href="#xtragrid-conditional-formatting-tooltip">#</a>Display Tooltips for Trimmed Conditional Formatting Rules
</h4>
<p> If formatting rule name is larger than the width of the cell, the rule will appear in a tooltip when you hover over the cell: </p>
<p></p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-winforms-grid-format-rule-tooltip.png"
srcset="/subscriptions/i/24.1/24-1-winforms-grid-format-rule-tooltip.png 1x, /subscriptions/i/24.1/24-1-winforms-grid-format-rule-tooltip@2x.png 2x"
alt="Display Tooltips for Trimmed Conditional Formatting Rules - WinForms Data Grid, DevExpress" width="906" height="459" style="border: none" id="ctl00_ctl00_Content_Content_ctl670"></div>
<p></p>
<div class="grid block-grid sys-max-width-lg-80 sys-visibility-hidden sys-visibility-hidden sys-visibility-sm-shown">
<div class="row">
<div class="col-sm-3">
<a href="dxdemo://Win/XtraGrid/MainDemo/FormatRules" target="_blank" rel="noopener" class="Button Gray">
Run Demo
</a>
</div>
<div class="col-sm-9 sys-v-align-middle">
<span class="FootNote"> To execute this demo, you must first <br><a href="https://go.devexpress.com/DevexpressDownload_UniversalTrial.aspx" target="_blank" rel="noopener">
install the DevExpress WinForms product library
</a>. </span>
</div>
</div>
</div> <span class="H-Separator"></span>
<h4 anchor="xtragrid-annotate-conditional-formatting">
<a name="xtragrid-annotate-conditional-formatting" class="anchor visible-anchor" href="#xtragrid-annotate-conditional-formatting">#</a>Annotate Conditional Formatting Rules
</h4>
<p> With this option, you and your end-users can include descriptive text for conditional formatting rules, offering insights into the purpose and logic behind each rule. Implementing text descriptions for conditional formatting rules is
simple and intuitive. Users can add explanations directly in the Formatting Rule Editor, ensuring that context is available each time they view or change rules. </p>
<p> To enable this feature, set the
<a href="https://docs.devexpress.com/WindowsForms/DevExpress.XtraGrid.Views.Base.ColumnViewOptionsView.AllowFormatRuleDescription?v=24.1" target="_blank" rel="noopener">OptionsView.AllowFormatRuleDescription</a> property to
<strong>true</strong>. </p>
<p></p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-winforms-grid-format-rule-description.png"
srcset="/subscriptions/i/24.1/24-1-winforms-grid-format-rule-description.png 1x, /subscriptions/i/24.1/24-1-winforms-grid-format-rule-description@2x.png 2x" alt="Annotate Conditional Formatting Rules - WinForms Data Grid, DevExpress"
width="773" height="501" style="border: none" id="ctl00_ctl00_Content_Content_ctl690"></div>
<p></p>
<p><strong>Note</strong>: we also introduced this feature in our WinForms TreeList, VerticalGrid, and PivotGrid controls. </p> <span class="H-Separator"></span>
<h3 data-anchor="xtratreelist" data-toc-title="TreeList">
<a name="xtratreelist" class="anchor"></a>TreeList
</h3>
<h4 anchor="xtratreelist-expand-nodes-on-search">
<a name="xtratreelist-expand-nodes-on-search" class="anchor visible-anchor" href="#xtratreelist-expand-nodes-on-search">#</a>Expand Nodes on Search
</h4>
<p> With this new feature, users can effortlessly locate specific TreeList nodes, even if they are collapsed within a complex hierarchy. When users initiate a search within the DevExpress TreeList, the TreeList automatically expands
relevant nodes to display search results (in previous versions, you could only search through expanded nodes). </p>
<p> Use the TreeList's <a href="https://docs.devexpress.com/WindowsForms/DevExpress.XtraTreeList.Columns.TreeListOptionsFind.ExpandNodesOnSearch?v=24.1" target="_blank" rel="noopener">OptionsFind.ExpandNodesOnSearch</a> setting to
enable/disable the "Expand Nodes on Search" feature. </p>
<p></p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-winforms-treelist-search.gif" srcset="/subscriptions/i/24.1/24-1-winforms-treelist-search.gif 1x, /subscriptions/i/24.1/24-1-winforms-treelist-search@2x.gif 2x"
alt="Expand Nodes on Search - WinForms TreeList, DevExpress" width="1008" height="444" style="border: none" id="ctl00_ctl00_Content_Content_ctl712"></div>
<p></p>
<div class="grid block-grid sys-max-width-lg-80 sys-visibility-hidden sys-visibility-hidden sys-visibility-sm-shown">
<div class="row">
<div class="col-sm-3">
<a href="dxdemo://Win/XtraTreeList/MainDemo/HierarchyColumn" target="_blank" rel="noopener" class="Button Gray">
Run Demo
</a>
</div>
<div class="col-sm-9 sys-v-align-middle">
<span class="FootNote"> To execute this demo, you must first <br><a href="https://go.devexpress.com/DevexpressDownload_UniversalTrial.aspx" target="_blank" rel="noopener">
install the DevExpress WinForms product library
</a>. </span>
</div>
</div>
</div> <span class="H-Separator"></span>
<h4 anchor="xtratreelist-performance">
<a name="xtratreelist-performance" class="anchor visible-anchor" href="#xtratreelist-performance">#</a>Improved Performance for Large Data Sources
</h4>
<p> We improved WinFroms TreeList performance to better address usage scenarios when large data updates are made to the underlying data source. </p>
<p> The following internal test results illustrate performance improvements: </p>
<p><img src="/subscriptions/i/24.1/24-1-winforms-treelist-performance.png" alt="Improved Performance for Large Data Sources - WinForms TreeList, DevExpress" width="770" height="544" style="border: none"
id="ctl00_ctl00_Content_Content_ctl726"></p> <span class="H-Separator"></span>
<h4 anchor="xtratreelist-autofilterrow">
<a name="xtratreelist-autofilterrow" class="anchor visible-anchor" href="#xtratreelist-autofilterrow">#</a>Auto-Filter Row Focus Retention
</h4>
<p> This addition to our WinForms TreeList control ensures that user focus remains unaffected when using the Auto-Filter Row, even during data updates. </p>
<p> In previous versions, the TreeList automatically closed the active editor in the Auto-Filter Row when updating data. In v24.1, the editor remains active (users can edit filter criteria during data updates). </p> <span
class="H-Separator"></span>
<h3 data-anchor="xtraaccordion" data-toc-title="Accordion">
<a name="xtraaccordion" class="anchor"></a>Accordion
</h3>
<h4 anchor="xtraaccordion-minimized-item-captions">
<a name="xtraaccordion-minimized-item-captions" class="anchor visible-anchor" href="#xtraaccordion-minimized-item-captions">#</a>Display Item Captions in a Minimized State
</h4>
<p> We added a new <a href="https://docs.devexpress.com/WindowsForms/DevExpress.XtraBars.Navigation.OptionsMinimizing.CaptionShowMode?v=24.1" target="_blank" rel="noopener">CaptionShowMode</a> property to control how the item caption is
displayed when the Accordion control is minimized/collapsed. </p>
<p> Options include: </p>
<ul>
<li>Below Image</li>
<li>Above Image</li>
<li>None</li>
</ul>
<p> The new <a href="https://docs.devexpress.com/WindowsForms/DevExpress.XtraBars.Navigation.OptionsMinimizing.CaptionImageIndent?v=24.1" target="_blank" rel="noopener">CaptionImageIndent</a> property specifies the indent between the
image and caption. </p>
<p></p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-winforms-accordion-minimized-item-text.png" alt="Display Item Captions in a Minimized State - WinForms Accordion Control, DevExpress" width="428" height="440"
style="border: none" id="ctl00_ctl00_Content_Content_ctl760"></div>
<p></p> <span class="H-Separator"></span>
<h4 anchor="xtraaccordion-item-indents">
<a name="xtraaccordion-item-indents" class="anchor visible-anchor" href="#xtraaccordion-item-indents">#</a>Configurable Item Indents
</h4>
<p> With this new option, you can introduce fully personalized side navigation logic. We added the
<a href="https://docs.devexpress.com/WindowsForms/DevExpress.XtraBars.Navigation.AccordionControl.ChildIndentStartLevel?v=24.1" target="_blank" rel="noopener">ChildIndentStartLevel</a> property. This property specifies the hierarchy
level that starts the indentation of child elements. </p>
<p> We also implemented a new <a href="https://docs.devexpress.com/WindowsForms/DevExpress.XtraBars.Navigation.AccordionControl.QueryElementIndent?v=24.1" target="_blank" rel="noopener">QueryElementIndent</a> event that allows you to
adjust the indent for specific accordion items based on design preferences/requirements. </p>
<p></p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-winforms-accordion-configurable-item-indent.png" alt="Configurable Item Indents - WinForms Accordion Control, DevExpress" width="570" height="428" style="border: none"
id="ctl00_ctl00_Content_Content_ctl778"></div>
<p></p> <span class="H-Separator"></span>
<h3 data-anchor="xtraribbon" data-toc-title="Ribbon & Bars">
<a name="xtraribbon" class="anchor"></a>Ribbon & Bars
</h3>
<h4 anchor="xtraribbon-page-keytip">
<a name="xtraribbon-page-keytip" class="anchor visible-anchor" href="#xtraribbon-page-keytip">#</a>Page Key Tips
</h4>
<p> We added a new <a href="https://docs.devexpress.com/WindowsForms/DevExpress.XtraBars.Ribbon.RibbonControl.ShowPageKeyTipsMode?v=24.1" target="_blank" rel="noopener">ShowPageKeyTipsMode</a> property. Use this property to configure the
display of page key tips within the Ribbon UI. This enhancement allows users - who prefer to use keyboard shortcuts instead of mouse input - to quickly navigate through different Ribbon sections and access specific commands (without
unnecessary keystrokes). </p>
<p> Options include: </p>
<ul>
<li><code data-renderer="hljs" class="csharp" data-control="Code-Inline">Hide</code> - Hides key tips for all Ribbon pages.</li>
<li><code data-renderer="hljs" class="csharp" data-control="Code-Inline">ShowOnMultiplePages</code> - Displays key tips only if the Ribbon UI displays multiple pages.</li>
<li><code data-renderer="hljs" class="csharp" data-control="Code-Inline">Show</code> (Default) - Displays key tips for all visible Ribbon pages and for the selected page (even if the selected page is hidden).</li>
</ul> <span class="H-Separator"></span>
<h4 anchor="xtraribbon-checkstate-image">
<a name="xtraribbon-checkstate-image" class="anchor visible-anchor" href="#xtraribbon-checkstate-image">#</a>BarCheckItem – Checked-state Image
</h4>
<p> You can now specify different images (bitmap or SVG) for checked and unchecked states of checkbox items (<code data-renderer="hljs" class="csharp" data-control="Code-Inline">BarCheckItem</code>). </p>
<p></p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-winforms-ribbon-bars-checked-button-image.gif" alt="Checked-state Image - WinForms Ribbon Control, DevExpress" width="316" height="116" style="border: none"
id="ctl00_ctl00_Content_Content_ctl807"></div>
<p></p>
<p>New APIs include:</p>
<ul>
<li><a href="https://docs.devexpress.com/WindowsForms/DevExpress.XtraBars.BarCheckItemImageOptions.CheckedImage?v=24.1" target="_blank" rel="noopener">CheckedImage</a> /
<a href="https://docs.devexpress.com/WindowsForms/DevExpress.XtraBars.BarCheckItemImageOptions.CheckedImageIndex?v=24.1" target="_blank" rel="noopener">CheckedImageIndex</a> /
<a href="https://docs.devexpress.com/WindowsForms/DevExpress.XtraBars.BarCheckItemImageOptions.CheckedImageKey?v=24.1" target="_blank" rel="noopener">CheckImageKey</a></li>
<li><a href="https://docs.devexpress.com/WindowsForms/DevExpress.XtraBars.BarCheckItemImageOptions.CheckedLargeImage?v=24.1" target="_blank" rel="noopener">CheckedLargeImage</a> /
<a href="https://docs.devexpress.com/WindowsForms/DevExpress.XtraBars.BarCheckItemImageOptions.CheckedLargeImageIndex?v=24.1" target="_blank" rel="noopener">CheckedLargeImageIndex</a> /
<a href="https://docs.devexpress.com/WindowsForms/DevExpress.XtraBars.BarCheckItemImageOptions.CheckedLargeImageKey?v=24.1" target="_blank" rel="noopener">CheckLargeImageKey</a></li>
<li><a href="https://docs.devexpress.com/WindowsForms/DevExpress.XtraBars.BarCheckItemImageOptions.CheckedSvgImage?v=24.1" target="_blank" rel="noopener">CheckedSVGImage</a></li>
</ul> <span class="H-Separator"></span>
<h4 anchor="xtraribbon-execute-command">
<a name="xtraribbon-execute-command" class="anchor visible-anchor" href="#xtraribbon-execute-command">#</a>Press Enter to Execute a Command
</h4>
<p> We extended available user interactions within the command search box. Users can execute commands without the need for additional clicks or interactions. Handle the new
<a href="https://docs.devexpress.com/WindowsForms/DevExpress.XtraBars.Ribbon.RibbonControl.SearchMenuEnterPressed?v=24.1" target="_blank" rel="noopener">SearchMenuEnterPressed</a> event to execute a command based on freely written text
or the first found command instantly when the user performs a search and presses the Enter key. </p> <span class="H-Separator"></span>
<h4 anchor="xtraribbon-customize-search-menu">
<a name="xtraribbon-customize-search-menu" class="anchor visible-anchor" href="#xtraribbon-customize-search-menu">#</a>Manage and Display Relevant Commands within the Search Menu Popup
</h4>
<p> Our Ribbon Control exposes a <a href="https://docs.devexpress.com/WindowsForms/DevExpress.XtraBars.Ribbon.RibbonControl.CustomizeSearchMenu?v=24.1" target="_blank" rel="noopener">CustomizeSearchMenu</a> event. This event allows you to
implement custom logic to determine which commands must appear in search results. v24.1 extends the event's arguments to simplify customization. </p>
<p> New APIs include: </p>
<ul>
<li><code data-renderer="hljs" class="csharp" data-control="Code-Inline">e.AddHeader(<span class="hljs-built_in">string</span> caption)</code> – Displays the header with a specific caption.</li>
<li><code data-renderer="hljs" class="csharp" data-control="Code-Inline">e.AddItem(BarItem item)</code> – Displays the specified command in search results.</li>
<li><code data-renderer="hljs" class="csharp" data-control="Code-Inline">e.ShowNoMatchesItem</code> – Specifies whether to display “No matches found” when a search query does not return results.</li>
</ul>
<p><img src="/subscriptions/i/24.1/24-1-winforms-ribbon-custom-search-results.png"
srcset="/subscriptions/i/24.1/24-1-winforms-ribbon-custom-search-results.png 1x, /subscriptions/i/24.1/24-1-winforms-ribbon-custom-search-results@2x.png 2x"
alt="Manage and Display Relevant Commands within the Search Menu Popup - WinForms Ribbon Control, DevExpress" width="859" height="555" style="border: none" id="ctl00_ctl00_Content_Content_ctl837"></p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">C#</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="csharp"><span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">ribbonControl1_CustomizeSearchMenu</span>(<span class="hljs-params"><span class="hljs-built_in">object</span> sender, RibbonSearchMenuEventArgs e</span>)</span> {
<span class="hljs-keyword">if</span>(e.SearchString.ToLower() == <span class="hljs-string">"format"</span>) {
e.AddHeader(<span class="hljs-string">"Text Formatting"</span>);
e.AddItem(ribbonControl1.Items[<span class="hljs-string">"iBold"</span>]);
e.AddItem(ribbonControl1.Items[<span class="hljs-string">"iItalic"</span>]);
e.AddItem(ribbonControl1.Items[<span class="hljs-string">"iUnderline"</span>]);
e.ShowNoMatchesItem = <span class="hljs-literal">false</span>;
}
}</code></pre>
</div>
</div>
<p> We introduced the <a href="https://docs.devexpress.com/WindowsForms/DevExpress.XtraBars.Ribbon.RibbonOptionsSearchMenu.UseCustomRibbonSearch?v=24.1" target="_blank" rel="noopener">UseCustomRibbonSearch</a> property for those who
prefer to generate search results from scratch. When set to <strong>true</strong>, our Ribbon Control does not auto-populate search results (<code data-renderer="hljs" class="csharp" data-control="Code-Inline">e.Menu.ItemLinks</code>).
You won't need to clear pre-built search results before adding your own commands. </p>
<p> Use the <a href="https://docs.devexpress.com/WindowsForms/DevExpress.XtraBars.Ribbon.RibbonControl.OptionsSearchMenu?v=24.1" target="_blank" rel="noopener">RibbonControl.OptionsSearchMenu</a> property to access search-related
settings. These include: </p>
<ul>
<li><a href="https://docs.devexpress.com/WindowsForms/DevExpress.XtraBars.Ribbon.RibbonOptionsSearchMenu.SearchItemPosition?v=24.1" target="_blank" rel="noopener">SearchItemPosition</a></li>
<li><a href="https://docs.devexpress.com/WindowsForms/DevExpress.XtraBars.Ribbon.RibbonOptionsSearchMenu.SearchItemShortcut?v=24.1" target="_blank" rel="noopener">SearchItemShortcut</a></li>
<li><a href="https://docs.devexpress.com/WindowsForms/DevExpress.XtraBars.Ribbon.RibbonOptionsSearchMenu.UseCustomRibbonSearch?v=24.1" target="_blank" rel="noopener">UseCustomRibbonSearch</a></li>
</ul> <span class="H-Separator"></span>
<h4 anchor="xtraribbon-merge-messages">
<a name="xtraribbon-merge-messages" class="anchor visible-anchor" href="#xtraribbon-merge-messages">#</a>Merge Ribbon Messages (MDI)
</h4>
<p> The Ribbon control of a parent Form displays <a href="https://docs.devexpress.com/WindowsForms/404480/controls-and-libraries/ribbon-bars-and-menu/ribbon/visual-elements/ribbon-message" target="_blank" rel="noopener">messages</a>
(Office-inspired flyout notifications and alerts) of Ribbon controls displayed on child MDI Forms when merged: </p>
<p> Use the <a href="https://docs.devexpress.com/WindowsForms/DevExpress.XtraBars.Ribbon.RibbonControl.MergedMessages?v=24.1" target="_blank" rel="noopener">RibbonControl.MergedMessages</a> property to access and manage merged messages.
</p>
<p><img src="/subscriptions/i/24.1/24-1-winforms-ribbon-merge-messages-mdi.gif" srcset="/subscriptions/i/24.1/24-1-winforms-ribbon-merge-messages-mdi.gif 1x, /subscriptions/i/24.1/24-1-winforms-ribbon-merge-messages-mdi@2x.gif 2x"
alt="Merge Ribbon Messages (MDI) - WinForms Ribbon Control, DevExpress" width="908" height="583" style="border: none" id="ctl00_ctl00_Content_Content_ctl872"></p> <span class="H-Separator"></span>
<h3 data-anchor="xtraeditors" data-toc-title="Data Editors">
<a name="xtraeditors" class="anchor"></a>Data Editors
</h3>
<h4 anchor="xtraeditors-">
<a name="xtraeditors-" class="anchor visible-anchor" href="#xtraeditors-">#</a>DateEdit – DateOnly Type Support
</h4>
<p> Our WinForms DateEdit control now supports the <code data-renderer="hljs" class="csharp" data-control="Code-Inline">DateOnly</code> data type. The following properties accept <code data-renderer="hljs" class="csharp"
data-control="Code-Inline">DateOnly</code> values: </p>
<ul>
<li><code data-renderer="hljs" class="csharp" data-control="Code-Inline"><span class="hljs-keyword">public</span> DateOnly DateOnly { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }</code></li>
<li><code data-renderer="hljs" class="csharp" data-control="Code-Inline"><span class="hljs-keyword">public</span> <span class="hljs-built_in">object</span> MinDate { <span class="hljs-keyword">get</span>; <span
class="hljs-keyword">set</span>; }</code></li>
<li><code data-renderer="hljs" class="csharp" data-control="Code-Inline"><span class="hljs-keyword">public</span> <span class="hljs-built_in">object</span> MaxDate { <span class="hljs-keyword">get</span>; <span
class="hljs-keyword">set</span>; }</code></li>
</ul> <span class="H-Separator"></span>
<h4 anchor="xtraeditors-custom-paint-button">
<a name="xtraeditors-custom-paint-button" class="anchor visible-anchor" href="#xtraeditors-custom-paint-button">#</a>Simple Button – Custom Painting
</h4>
<p> We implemented a new <a href="https://docs.devexpress.com/WindowsForms/DevExpress.XtraEditors.SimpleButton.CustomDraw?v=24.1" target="_blank" rel="noopener">CustomDraw</a> event. Handle this event to paint our WinForms Simple Button
manually. </p>
<p></p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-winforms-simplebutton-customdraw.png"
srcset="/subscriptions/i/24.1/24-1-winforms-simplebutton-customdraw.png 1x, /subscriptions/i/24.1/24-1-winforms-simplebutton-customdraw@2x.png 2x" alt="Custom Paint a Simple Button - WinForms Data Editors, DevExpress" width="311"
height="44" style="border: none" id="ctl00_ctl00_Content_Content_ctl901"></div>
<p></p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">C#</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="csharp"><span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">simpleButton1_CustomDraw</span>(<span class="hljs-params"><span class="hljs-built_in">object</span> sender, DevExpress.XtraEditors.ButtonCustomDrawEventArgs e</span>)</span> {
<span class="hljs-keyword">if</span>(e.Info.State == DevExpress.Utils.Drawing.ObjectState.Hot) {
e.Cache.FillRectangle(Brushes.Orange, e.Bounds);
e.DefaultDrawImage();
e.DefaultDrawText();
e.Handled = <span class="hljs-literal">true</span>;
}
}</code></pre>
</div>
</div> <span class="H-Separator"></span>
<h4 anchor="xtraeditors-unified-paddings">
<a name="xtraeditors-unified-paddings" class="anchor visible-anchor" href="#xtraeditors-unified-paddings">#</a>Unified Padding Settings for Textbox-based Editors
</h4>
<p> v24.1 ships with consistent padding settings across all DevExpress Textbox-based data editor types (such as TextEdit, SpinEdit, DateEdit, MemoEdit, etc.). These settings allow you to maintain visual consistency without having to
specify different padding options for different editor types. </p>
<p> Use <code data-renderer="hljs" class="csharp" data-control="Code-Inline">Properties.TextPadding</code> and <code data-renderer="hljs" class="csharp" data-control="Code-Inline">Properties.Padding</code> properties to specify text and
content paddings within the text box. </p>
<p></p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-winforms-editors-text-paddings.png" alt="Unified Padding Settings for Textbox-based Editors - WinForms Data Editors, DevExpress" width="678" height="203" style="border: none"
id="ctl00_ctl00_Content_Content_ctl918"></div>
<p></p> <span class="H-Separator"></span>
<h4 anchor="xtraeditors-memoedit-wxi">
<a name="xtraeditors-memoedit-wxi" class="anchor visible-anchor" href="#xtraeditors-memoedit-wxi">#</a>MemoEdit – Enhanced WXI Skin Visualization
</h4>
<p> We enhanced the visualization of MemoEdit borders and added scrollbar colorization within our WXI Skin. Accordingly, the DevExpress WinForms MemoEdit now supports DevExpress Skin colors. </p>
<p></p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-winforms-memoedit-wxi.png" srcset="/subscriptions/i/24.1/24-1-winforms-memoedit-wxi.png 1x, /subscriptions/i/24.1/24-1-winforms-memoedit-wxi@2x.png 2x"
alt="Enhanced WXI Skin Visualization of the MemoEdit - WinForms Data Editors, DevExpress" width="244" height="143" style="border: none" id="ctl00_ctl00_Content_Content_ctl928"></div>
<p></p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">C#</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="csharp">memoEdit1.Properties.Appearance.BackColor = DevExpress.LookAndFeel.DXSkinColors.FillColors.Question;</code></pre>
</div>
</div> <span class="H-Separator"></span>
<h4 anchor="xtraeditors-edit-value">
<a name="xtraeditors-edit-value" class="anchor visible-anchor" href="#xtraeditors-edit-value">#</a>Distinguish User vs. Code Modifications to the Editor's Value
</h4>
<p> You can now distinguish between modifications made by a user and those made programmatically (in code) to the editor's value. We added a <code data-renderer="hljs" class="csharp" data-control="Code-Inline">e.ModifiedByUser</code>
parameter to arguments for the <a href="https://docs.devexpress.com/WindowsForms/DevExpress.XtraEditors.BaseEdit.EditValueChanging?v=24.1" target="_blank" rel="noopener">EditValueChanging</a> event: </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">C#</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="csharp"><span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">textEdit1_EditValueChanging</span>(<span class="hljs-params"><span class="hljs-built_in">object</span> sender, DevExpress.XtraEditors.Controls.ChangingEventArgs e</span>)</span> {
<span class="hljs-keyword">if</span>(e.ModifiedByUser) {
<span class="hljs-comment">// ...</span>
}
}</code></pre>
</div>
</div> <span class="H-Separator"></span>
<h3 data-anchor="xtradocumentmanager" data-toc-title="Document Manager">
<a name="xtradocumentmanager" class="anchor"></a>Document Manager
</h3>
<h4 anchor="xtradocumentmanager-add-content-at-designtime">
<a name="xtradocumentmanager-add-content-at-designtime" class="anchor visible-anchor" href="#xtradocumentmanager-add-content-at-designtime">#</a>Adding Content at Design-Time
</h4>
<p> Our Document Manager supports deferred loading. To leverage this capability, document content must be generated at runtime in the
<a href="https://docs.devexpress.com/WindowsForms/DevExpress.XtraBars.Docking2010.Views.BaseView.QueryControl?v=24.1" target="_blank" rel="noopener">QueryControl</a> event handler. While this technique offers flexibility and performance
benefits, it may be complicated for simple usage scenarios (where all documents are known at design-time). </p>
<p> In v24.1, you can add User Controls and Forms to documents at design time (in Visual Studio). </p>
<p><img src="/subscriptions/i/24.1/24-1-winforms-document-manager-design-time-customization.gif"
srcset="/subscriptions/i/24.1/24-1-winforms-document-manager-design-time-customization.gif 1x, /subscriptions/i/24.1/24-1-winforms-document-manager-design-time-customization@2x.gif 2x"
alt="Adding Content at Design-Time - WinForms Document Manager, DevExpress" width="980" height="664" style="border: none" id="ctl00_ctl00_Content_Content_ctl961"></p> <span class="H-Separator"></span>
<h3 data-anchor="xtradocking" data-toc-title="Docking Library">
<a name="xtradocking" class="anchor"></a>Docking Library
</h3>
<h4 anchor="xtradocking-layout-restore-validation">
<a name="xtradocking-layout-restore-validation" class="anchor visible-anchor" href="#xtradocking-layout-restore-validation">#</a>Layout Restore Validation
</h4>
<p> You can now ensure the integrity and consistency of docking layouts during deserialization. Inconsistency or corruption of deserialized layout data can result in unexpected behavior, visual artifacts, or application crashes. The
<a href="https://docs.devexpress.com/WindowsForms/DevExpress.XtraBars.Docking.DockManager.RestoreLayoutError?v=24.1" target="_blank" rel="noopener">RestoreLayoutError</a> event allows you to prevent loading of broken layouts or to
handle/fix layout-related issues as needed: </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">C#</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="csharp"><span class="hljs-keyword">using</span> DevExpress.Utils.Serializing;
<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">dockManager1_RestoreLayoutError</span>(<span class="hljs-params"><span class="hljs-built_in">object</span> sender, RestoreLayoutErrorEventArgs e</span>)</span> {
<span class="hljs-keyword">foreach</span> (<span class="hljs-keyword">var</span> exception <span class="hljs-keyword">in</span> e.Exceptions) {
<span class="hljs-keyword">if</span> (exception <span class="hljs-keyword">is</span> TabContainerActiveChildNotSetException activeChildException)
activeChildException.Panel.ActiveChild = activeChildException.Panels[<span class="hljs-number">1</span>];
}
e.Throw = <span class="hljs-literal">false</span>;
}</code></pre>
</div>
</div>
<p><strong>Note</strong>: we also added layout restore validation in our WinForms Document Manager
(<a href="https://docs.devexpress.com/WindowsForms/DevExpress.XtraBars.Docking2010.Views.BaseView.RestoreLayoutError?v=24.1" target="_blank" rel="noopener">RestoreLayoutError</a>). </p> <span class="H-Separator"></span>
<h3 data-anchor="winforms-html-css-support" data-toc-title="HTML & CSS Support">
<a name="winforms-html-css-support" class="anchor"></a>HTML & CSS Support
</h3>
<h4 anchor="winforms-html-css-code-snippets">
<a name="winforms-html-css-code-snippets" class="anchor visible-anchor" href="#winforms-html-css-code-snippets">#</a>Pre-Written Code Snippets for HTML/CSS
</h4>
<p> v24.1 includes 40 pre-written HTML & CSS code snippets in our HTML Template Designer for Visual Studio. These are optimized code snippets that address common HTML-related tasks. </p>
<p></p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-winforms-html-css-snippets.png" srcset="/subscriptions/i/24.1/24-1-winforms-html-css-snippets.png 1x, /subscriptions/i/24.1/24-1-winforms-html-css-snippets@2x.png 2x"
alt="Pre-Written Code Snippets for HTML/CSS - WinForms Controls, DevExpress" width="894" height="564" style="border: none" id="ctl00_ctl00_Content_Content_ctl996"></div>
<p></p>
<p> Code snippets include: </p>
<ul>
<li>Basic Elements (border, picture, link, tooltip, list, table)</li>
<li>Text & Font Snippets</li>
<li>Layout Snippets</li>
<li>Colors & Visual Elements</li>
<li>Binding Snippets</li>
</ul> <span class="H-Separator"></span>
<h4 anchor="winforms-html-css-align-editor-text">
<a name="winforms-html-css-align-editor-text" class="anchor visible-anchor" href="#winforms-html-css-align-editor-text">#</a>Align Editor Text
</h4>
<p> You can now use standard CSS properties to align DevExpress editor content (horizontally or vertically) used within HTML templates. </p>
<p></p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-winforms-html-css-text-align.png" srcset="/subscriptions/i/24.1/24-1-winforms-html-css-text-align.png 1x, /subscriptions/i/24.1/24-1-winforms-html-css-text-align@2x.png 2x"
alt="Align Editor Text - WinForms HTML/CSS Support, DevExpress" width="862" height="595" style="border: none" id="ctl00_ctl00_Content_Content_ctl1009"></div>
<p></p> <span class="H-Separator"></span>
<h3 data-anchor="xtrapdfviewer" data-toc-title="PDF Viewer">
<a name="xtrapdfviewer" class="anchor"></a>PDF Viewer
</h3>
<h4 anchor="xtrapdfviewer-signature-info-panel">
<a name="xtrapdfviewer-signature-info-panel" class="anchor visible-anchor" href="#xtrapdfviewer-signature-info-panel">#</a>Signature Info Panel
</h4>
<p> With our new <strong>Signature Info</strong> panel, you can display detailed information for each signature in the loaded document and verify signature validity. </p>
<p> When you open a document, the PDF Viewer verifies signatures and displays associated status in the Signature panel (valid, invalid, or unknown). </p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-winforms-pdfviewer-signature-info-panel.png"
srcset="/subscriptions/i/24.1/24-1-winforms-pdfviewer-signature-info-panel.png 1x, /subscriptions/i/24.1/24-1-winforms-pdfviewer-signature-info-panel@2x.png 2x" alt="Signature Info Panel - WinForms PDF Viewer, DevExpress" width="607"
height="472" style="border: none" id="ctl00_ctl00_Content_Content_ctl1026"></div>
<p> In addition, the new panel displays the following signature-related information: </p>
<ul>
<li>Location of the signature in the document</li>
<li>Signer's information</li>
<li>Reasons the signature was created</li>
<li>Date and time when the document was singed and modified once it was signed</li>
<li>Certificate information.</li>
</ul>
<p><a href="https://www.devexpress.com/subscriptions/whats-new/beta/#xtrapdfviewer-signature-info-panel
https://docs.devexpress.com/WindowsForms/115232/controls-and-libraries/pdf-viewer/visual-elements/navigation-pane?v=24.1#signatures" target="_blank" rel="noopener">Documentation</a></p> <span class="H-Separator"></span>
<h4 anchor="xtrapdfviewer-layers">
<a name="xtrapdfviewer-layers" class="anchor visible-anchor" href="#xtrapdfviewer-layers">#</a>Layers
</h4>
<p> PDF document layers allow you to selectively view or hide specific content sections. The main purpose of layers is to control the visibility of graphics objects rendered in a PDF document across different states (when you view or
print a PDF document). </p>
<p> We added a <strong>Layers</strong> panel to display all layers contained in a document. This new capability allows you to change layer visibility via the UI. Click the check box next to the layer's name in the new Layers panel to
display/hide a given document layer. Visible layers are highlighted using an “eye” icon; layers that cannot be hidden because of a document configuration do not have a check box next to their name. </p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-winforms-pdfviewer-layers.png" srcset="/subscriptions/i/24.1/24-1-winforms-pdfviewer-layers.png 1x, /subscriptions/i/24.1/24-1-winforms-pdfviewer-layers@2x.png 2x"
alt="Layers - WinForms PDF Viewer, DevExpress" width="870" height="400" style="border: none" id="ctl00_ctl00_Content_Content_ctl1046"></div>
<p> With the power of the <strong>PDF Facade API</strong>, you can also access and manage layer visibility at runtime when you preview or print your PDF documents. Call the
<a href="https://docs.devexpress.com/OfficeFileAPI/DevExpress.Pdf.PdfViewerExtensions.GetDocumentFacade(DevExpress.Pdf.IPdfViewer)?v=24.1" target="_blank" rel="noopener">PdfViewerExtensions.GetDocumentFacade</a> extension method to
obtain the PdfDocumentFacade class object (it allows you to change the PDF document without access to its inner structure) and use the
<a href="https://docs.devexpress.com/OfficeFileAPI/DevExpress.Pdf.PdfDocumentFacade.OptionalContentVisibility?v=24.1" target="_blank" rel="noopener">PdfDocumentFacade.OptionalContentVisibility</a> collection to change the visibility
state for the required document layers in code. </p>
<div class="Attention">
<p class="sys-h-align-left"> The <code data-renderer="hljs" class="csharp" data-control="Code-Inline">PdfDocumentFacade</code> class is defined in the DevExpress.Docs.v24.1.dll assembly. Add this assembly to your project or install the
DevExpress.Document.Processor NuGet Package to use the <code data-renderer="hljs" class="csharp" data-control="Code-Inline">PdfDocumentFacade</code> members. You need a license for the
<a href="/products/net/office-file-api/#Pricing">DevExpress Office File API Subscription</a> or <a href="/buy">DevExpress Universal Subscription</a> to use this class in production code. </p>
</div>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">C#</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="csharp">pdfViewer.LoadDocument(<span class="hljs-string">"layers.pdf"</span>);
PdfDocumentFacade documentFacade = pdfViewer.GetDocumentFacade();
<span class="hljs-comment">// Set visibility for each Layer</span>
documentFacade.OptionalContentVisibility.Groups[<span class="hljs-number">0</span>].Visible = <span class="hljs-literal">false</span>;
documentFacade.OptionalContentVisibility.Groups[<span class="hljs-number">1</span>].Visible = <span class="hljs-literal">false</span>;
documentFacade.OptionalContentVisibility.Groups[<span class="hljs-number">2</span>].Visible = <span class="hljs-literal">true</span>;</code></pre>
</div>
</div>
<p><a href="https://docs.devexpress.com/WindowsForms/404949/controls-and-libraries/pdf-viewer/additional-content/layers?v=24.1" target="_blank" rel="noopener">Documentation</a></p> <span class="H-Separator"></span>
<h3 data-anchor="xtrarichtextedit" data-toc-title="Rich Text Editor">
<a name="xtrarichtextedit" class="anchor"></a>Rich Text Editor
</h3>
<h4 anchor="xtrarichtextedit-screen-readers-support">
<a name="xtrarichtextedit-screen-readers-support" class="anchor visible-anchor" href="#xtrarichtextedit-screen-readers-support">#</a>Accessibility - Screen Readers Support
</h4>
<p> v24.1 adds support for key accessibility-related requirements, including the ability for assistive technologies (such as screen readers) to read text in the body of a document, alternative text and names for images, text box content,
headers, and footers. </p> <span class="H-Separator"></span>
<h4 anchor="xtrarichtextedit-export-to-accessible-pdf">
<a name="xtrarichtextedit-export-to-accessible-pdf" class="anchor visible-anchor" href="#xtrarichtextedit-export-to-accessible-pdf">#</a>Export to Accessible PDF
</h4>
<p> We extended accessibility-related support to the following elements when exporting Word documents to accessible PDF files: </p>
<ul>
<li>Table of Contents tagging</li>
<li>Metadata fields</li>
<li>Alt text handling</li>
<li>Tables</li>
<li>Floating objects.</li>
</ul>
<p> Adobe Acrobat Pro and PDF Accessibility Checker 2024 were used for quality control. Our test documents successfully passed validation for PDF/UA compatibility and WCAG 2.1 compliance. </p>
<p> Accessibility-related export enhancements are available out-of-the-box when you specify the <code data-renderer="hljs" class="csharp" data-control="Code-Inline">PdfUACompatibility</code> option: </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">C#</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="csharp"><span class="hljs-keyword">using</span> System.IO;
<span class="hljs-keyword">using</span> DevExpress.XtraRichEdit;
<span class="hljs-comment">//...</span>
<span class="hljs-keyword">using</span>(FileStream stream =
<span class="hljs-keyword">new</span> FileStream(resultFilePath, FileMode.Create, FileAccess.Write, FileShare.Read)) {
PdfExportOptions exportOptions = <span class="hljs-keyword">new</span> PdfExportOptions();
exportOptions.PdfUACompatibility = PdfUACompatibility.PdfUA1;
richEditControl.ExportToPdf(stream, exportOptions);
}</code></pre>
</div>
</div> <span class="H-Separator"></span>
<h4 anchor="xtrarichtextedit-decorative-shapes">
<a name="xtrarichtextedit-decorative-shapes" class="anchor visible-anchor" href="#xtrarichtextedit-decorative-shapes">#</a>Decorative Shapes
</h4>
<p> We added a <code data-renderer="hljs" class="csharp" data-control="Code-Inline">Decorative</code> property for the
<a href="https://docs.devexpress.com/OfficeFileAPI/DevExpress.XtraRichEdit.API.Native.DrawingObject.Decorative?v=24.1" target="_blank" rel="noopener">Shape</a> class to mark document graphics (pictures, shapes, and charts) as
decorative. Decorative shapes add visual interest, but they are not informative. Thus, you do not need to specify Alt Text (meaningful description) for decorative objects when you generate an accessible document. </p> <span
class="H-Separator"></span>
<h4 anchor="xtrarichtextedit-math-equations">
<a name="xtrarichtextedit-math-equations" class="anchor visible-anchor" href="#xtrarichtextedit-math-equations">#</a>Math Equations
</h4>
<p> Our Rich Text Editor now preserves Math Equations when saving a document. You can import your Word documents with Math Equations in our WinForms Rich Text Editor and save them to the RTF and OpenXml (.docx/.docm) formats without
content loss. </p>
<p><strong>Note</strong>: Math Equations will be printed or exported to PDF only if the source document contains a fallback image for a Math Equation. To suppress Math Equation import, set the
<a href="https://docs.devexpress.com/OfficeFileAPI/DevExpress.XtraRichEdit.DocumentCapabilitiesOptions.MathEquations?v=24.1" target="_blank" rel="noopener">DocumentCapabilities.MathEquations</a> property to <code data-renderer="hljs"
class="csharp" data-control="Code-Inline">DocumentCapability.Disabled</code>. </p> <span class="H-Separator"></span>
<h4 anchor="xtrarichtextedit-gutter-mirrored-margins">
<a name="xtrarichtextedit-gutter-mirrored-margins" class="anchor visible-anchor" href="#xtrarichtextedit-gutter-mirrored-margins">#</a>Gutter and Mirrored Margins
</h4>
<p> The DevExpress WinForms Rich Text Editor v24.1 allows you to specify gutter margins - extra space that ensures binding will not obscure text on printed pages. You can specify gutter position (top, left, and right) and margin size. Use
the <a href="https://docs.devexpress.com/OfficeFileAPI/DevExpress.XtraRichEdit.API.Native.Document.GutterAtTop?v=24.1" target="_blank" rel="noopener">Document.GutterAtTop</a>,
<a href="https://docs.devexpress.com/OfficeFileAPI/DevExpress.XtraRichEdit.API.Native.SectionMargins.GutterPosition?v=24.1" target="_blank" rel="noopener">SectionMargins.GutterPosition</a>, and
<a href="https://docs.devexpress.com/OfficeFileAPI/DevExpress.XtraRichEdit.API.Native.SectionMargins.Gutter?v=24.1" target="_blank" rel="noopener">SectionMargins.Gutter</a> properties to address specific usage requirements. </p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-winforms-rich-text-editor-gutter-and-mirrored-margins.png"
srcset="/subscriptions/i/24.1/24-1-winforms-rich-text-editor-gutter-and-mirrored-margins.png 1x, /subscriptions/i/24.1/24-1-winforms-rich-text-editor-gutter-and-mirrored-margins@2x.png 2x"
alt="Gutter and Mirrored Margins - DevExpress WinForms Rich Text Editor" width="411" height="344" style="border: none" id="ctl00_ctl00_Content_Content_ctl1149"></div>
<p> The following code snippet adds a left gutter to the first document section: </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">C#</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="csharp"><span class="hljs-keyword">using</span> DevExpress.XtraRichEdit;
<span class="hljs-keyword">using</span> DevExpress.XtraRichEdit.API.Native;
<span class="hljs-keyword">using</span> DevExpress.Office.Utils;
<span class="hljs-comment">//...</span>
richEditControl.LoadDocument(<span class="hljs-string">@"Documents//Alice.docx"</span>);
Document document = richEditControl.Document;
Section firstSection = wordProcessor.Document.Sections[<span class="hljs-number">0</span>];
<span class="hljs-keyword">var</span> pageMargins = firstSection.Margins;
pageMargins.GutterPosition = GutterPosition.Left;
pageMargins.Gutter = Units.InchesToDocumentsF(<span class="hljs-number">1</span>);
richEditControl.SaveDocument(<span class="hljs-string">"Alice_formatted.docx"</span>, DocumentFormat.OpenXml);</code></pre>
</div>
</div>
<p> Our new <a href="https://docs.devexpress.com/OfficeFileAPI/DevExpress.XtraRichEdit.API.Native.Document.MarginType?v=24.1" target="_blank" rel="noopener">Document.MarginType</a> property allows you to define a regular or mirrored
margin type. Enable mirrored margins if you print on both sides of the paper and want to bind the printout. </p>
<p> The following code snippet enables mirrored margins and specifies an additional space value: </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">C#</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="csharp"><span class="hljs-keyword">using</span> DevExpress.XtraRichEdit;
<span class="hljs-keyword">using</span> DevExpress.XtraRichEdit.API.Native;
<span class="hljs-keyword">using</span> DevExpress.Office.Utils;
<span class="hljs-comment">//...</span>
richEditControl.LoadDocument(<span class="hljs-string">@"Documents//Alice.docx"</span>);
Document document = richEditControl.Document;
<span class="hljs-comment">// Enable mirrored margins</span>
document.MarginsType = MarginsType.Mirrored;
<span class="hljs-keyword">foreach</span> (Section section <span class="hljs-keyword">in</span> richEditControl.Document.Sections) {
<span class="hljs-keyword">var</span> pageMargins = section.Margins;
<span class="hljs-comment">// Set the value for mirrored margins</span>
pageMargins.Gutter = Units.InchesToDocumentsF(<span class="hljs-number">0.5f</span>);
}
richEditControl.SaveDocument(<span class="hljs-string">"Alice_formatted.docx"</span>, DocumentFormat.OpenXml);</code></pre>
</div>
</div>
<p> New UI elements are also available. </p>
<p><a href="https://docs.devexpress.com/WindowsForms/9553/controls-and-libraries/rich-text-editor/rich-edit-control-document/sections?v=24.1#add-gutter-margins" target="_blank" rel="noopener">Documentation</a></p> <span
class="H-Separator"></span>
<h4 anchor="xtrarichtextedit-image-export-api">
<a name="xtrarichtextedit-image-export-api" class="anchor visible-anchor" href="#xtrarichtextedit-image-export-api">#</a>Image Export API
</h4>
<p> v24.1 includes new cross-platform APIs to export Word document pages to an image. This new capability allows you to generate document previews. With our new APIs, you can convert document pages to raster and vector images (PNG, JPEG,
BMP, multi-page Tiff, emf), save them as physical files on the disk or obtain a list of image streams for further processing in code. You can also set image background color, modify output image resolution, or generate thumbnail images
with a specified size. </p>
<p> The new API is available via the
<a href="https://docs.devexpress.com/OfficeFileAPI/DevExpress.XtraRichEdit.RichEditDocumentServerExtensions.ExportToImage.overloads?v=24.1" target="_blank" rel="noopener">RichEditDocumentServerExtensions.ExportToImage</a> extension
method of the <code data-renderer="hljs" class="csharp" data-control="Code-Inline">Document</code> object. </p>
<div class="Attention">
<p class="sys-h-align-left"> Please note that the <code data-renderer="hljs" class="csharp" data-control="Code-Inline">RichEditDocumentServerExtensions</code> class is defined in the DevExpress.Docs.v24.1.dll assembly. Add this assembly
to your project or install the "DevExpress.Document.Processor" NuGet Package to use the <code data-renderer="hljs" class="csharp" data-control="Code-Inline">RichEditDocumentServerExtensions</code> members. You need a license for the
<a href="/products/net/office-file-api/#Pricing">DevExpress Office File API Subscription</a> or <a href="/buy">DevExpress Universal Subscription</a> to use this class in production code. </p>
</div>
<p> The following code snippet exports the first document page to an image with a specified size and JPEG format: </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">C#</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="csharp"><span class="hljs-keyword">using</span> DevExpress.XtraRichEdit;
<span class="hljs-keyword">using</span> DevExpress.XtraRichEdit.Export.Image;
<span class="hljs-keyword">using</span> DevExpress.Drawing;
richEditControl.LoadDocument(<span class="hljs-string">@"C:\Documents\Alice.docx"</span>);
<span class="hljs-comment">//...</span>
RichEditImageExportOptions options = <span class="hljs-keyword">new</span> RichEditImageExportOptions();
options.Format = DXImageFormat.Jpeg;
options.PageRange = <span class="hljs-string">"1"</span>;
options.LargestEdgeLength = <span class="hljs-number">1080</span>;
richEditControl.Document.ExportToImage(<span class="hljs-string">@"C:\Documents\Image.jpeg"</span>, options);</code></pre>
</div>
</div> <span class="H-Separator"></span>
<h4 anchor="xtrarichtextedit-export-pages-to-svg">
<a name="xtrarichtextedit-export-pages-to-svg" class="anchor visible-anchor" href="#xtrarichtextedit-export-pages-to-svg">#</a>Export Document Pages to SVG
</h4>
<p> Our new Image Export APIs allow you to export document pages to SVG. Use the <code data-renderer="hljs" class="csharp" data-control="Code-Inline">RichEditImageExportOptions.Format</code> option to set SVG as a target image format.
</p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">C#</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="csharp">RichEditImageExportOptions options = <span class="hljs-keyword">new</span> RichEditImageExportOptions();
options.Format = DXImageFormat.Svg;
options.PageRange = <span class="hljs-string">"1"</span>;
richEditControl.Document.ExportToImage(<span class="hljs-string">@"C:\Documents\Image.svg"</span>, options);</code></pre>
</div>
</div>
<p> SVG Export is also available from the user interface - open the Print Preview dialog, click the Export to Image button, choose the SVG format in the Image Options dialog and complete document export. </p> <span
class="H-Separator"></span>
<h3 data-anchor="winforms-svg-scroll-cursor" data-toc-title="SVG Scroll Cursor">
<a name="winforms-svg-scroll-cursor" class="anchor"></a>SVG Scroll Cursor
</h3>
<p> WinForms data-aware controls with scrollable content now ship with DPI-independent scroll cursor (the cursor that appears when the user presses the middle mouse button), providing smooth and precise navigation regardless of screen
resolution. </p> <span class="H-Separator"></span>
<h3 data-anchor="xtraspreadsheet" data-toc-title="Spreadsheet">
<a name="xtraspreadsheet" class="anchor"></a>Spreadsheet
</h3>
<h4 anchor="xtraspreadsheet-accessibility">
<a name="xtraspreadsheet-accessibility" class="anchor visible-anchor" href="#xtraspreadsheet-accessibility">#</a>Accessibility Enhancements - Decorative Shapes
</h4>
<p> We added a <code data-renderer="hljs" class="csharp" data-control="Code-Inline">Decorative</code> property for the
<a href="https://docs.devexpress.com/OfficeFileAPI/DevExpress.Spreadsheet.Shape.Decorative?v=24.1" target="_blank" rel="noopener">Shape</a> class to mark document graphics (pictures, shapes and charts) as decorative. Decorative shapes
add visual interest, but they are not informative. Thus, you do not need to specify Alt Text (meaningful description) for decorative objects when you generate an accessible document. </p> <span class="H-Separator"></span>
<h4 anchor="xtraspreadsheet-text-align">
<a name="xtraspreadsheet-text-align" class="anchor visible-anchor" href="#xtraspreadsheet-text-align">#</a>Justify & Distributed Text Alignment
</h4>
<p> v24.1 adds support for <strong>Justify</strong> and <strong>Distributed</strong> horizontal alignment types within Spreadsheet cells. Excel files using these alignment options can be printed and exported to PDF. </p>
<p> You can use the <a href="https://docs.devexpress.com/OfficeFileAPI/DevExpress.Spreadsheet.Alignment.Horizontal" target="_blank" rel="noopener">Cell.Alignment.Horizontal</a> property to specify horizontal alignment in code. </p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-winforms-spreadsheet-justify-and-distributed-text-align.png"
srcset="/subscriptions/i/24.1/24-1-winforms-spreadsheet-justify-and-distributed-text-align.png 1x, /subscriptions/i/24.1/24-1-winforms-spreadsheet-justify-and-distributed-text-align@2x.png 2x"
alt="Justify and Distributed Text Alignment - WinForms Spreadsheet, DevExpress" width="515" height="327" style="border: none" id="ctl00_ctl00_Content_Content_ctl1252"></div>
<p> The following code snippet specifies alignment in code: </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">C#</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="csharp"><span class="hljs-keyword">var</span> workbook = <span class="hljs-keyword">new</span> Workbook();
<span class="hljs-keyword">var</span> worksheet = workbook.Worksheets[<span class="hljs-number">0</span>];
Cell cellA1 = worksheet.Cells[<span class="hljs-string">"A1"</span>];
cellA1.Value = <span class="hljs-string">"Justified and top"</span>;
cellA1.Alignment.Horizontal = SpreadsheetHorizontalAlignment.Justify;
cellA1.Alignment.Vertical = SpreadsheetVerticalAlignment.Top;
workbook.ExportToPdf(<span class="hljs-string">"Result.pdf"</span>);</code></pre>
</div>
</div> <span class="H-Separator"></span>
<h4 anchor="xtraspreadsheet-sort-filter-by-color">
<a name="xtraspreadsheet-sort-filter-by-color" class="anchor visible-anchor" href="#xtraspreadsheet-sort-filter-by-color">#</a>Sort and Filter by Color
</h4>
<p> The DevExpress WinForms Spreadsheet ships with enhanced filter and sort-related capabilities. We added new APIs that can sort and filter workbook data by background and font color. Cell ranges filtered/sorted by cell color can also be
printed and exported to PDF. </p>
<p> Our Sorting APIs include new <a href="https://docs.devexpress.com/OfficeFileAPI/DevExpress.Spreadsheet.Worksheet.Sort.overloads?v=24.1" target="_blank" rel="noopener">Worksheet.Sort</a> method overloads designed to sort a specified
range by font color or fill setting (background color and pattern). </p>
<p> The following code snippet sorts cell values across two cell ranges - the first is sorted by a red font color and the second is sorted by fill settings specified for the first cell in the range: </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">C#</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="csharp">spreadsheetControl.LoadDocument(<span class="hljs-string">"sort-filter.xlsx"</span>);
Worksheet worksheet = spreadsheetControl.ActiveWorksheet;
<span class="hljs-comment">// Sort cell range by font color </span>
worksheet.Sort(worksheet[<span class="hljs-string">"B2:B10"</span>], Color.Red);
<span class="hljs-comment">// Sort cell range by fill color</span>
worksheet.Sort(worksheet[<span class="hljs-string">"D2:D10"</span>], worksheet[<span class="hljs-string">"D2"</span>].Fill);</code></pre>
</div>
</div>
<p> To filter cells by font or background color, you need to apply an auto-filter to the required cell range or table. Once complete, you need to obtain the required column from the <code data-renderer="hljs" class="csharp"
data-control="Code-Inline">AutoFilter.Columns</code> collection and call one of the following methods: </p>
<ul>
<li><a href="https://docs.devexpress.com/OfficeFileAPI/DevExpress.Spreadsheet.AutoFilterColumn.ApplyFillColorFilter(System.Drawing.Color)?v=24.1" target="_blank" rel="noopener">AutoFilterColumn.ApplyFillColorFilter(Color)</a></li>
<li><a href="https://docs.devexpress.com/OfficeFileAPI/DevExpress.Spreadsheet.AutoFilterColumn.ApplyFillFilter(DevExpress.Spreadsheet.Fill)?v=24.1" target="_blank" rel="noopener">AutoFilterColumn.ApplyFillFilter(Fill)</a></li>
<li><a href="https://docs.devexpress.com/OfficeFileAPI/DevExpress.Spreadsheet.AutoFilterColumn.ApplyFontColorFilter(System.Drawing.Color)?v=24.1" target="_blank" rel="noopener">AutoFilterColumn.ApplyFontColorFilter(Color)</a></li>
</ul>
<p> The following code snippet uses these methods for both cell range and table: </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">C#</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="csharp">spreadsheetControl.LoadDocument(<span class="hljs-string">"sort-filter.xlsx"</span>);
Worksheet worksheet = spreadsheetControl.ActiveWorksheet;
<span class="hljs-comment">// Apply an auto-filter to a cell range and filter the first column by font color</span>
worksheet.AutoFilter.Apply(worksheet[<span class="hljs-string">"B1:B10"</span>]);
worksheet.AutoFilter.Columns[<span class="hljs-number">0</span>].ApplyFontColorFilter(Color.Red);
<span class="hljs-comment">// Create a table, apply an auto-filter and filter the first column by fill color</span>
Table table = worksheet.Tables.Add(worksheet[<span class="hljs-string">"B12:B21"</span>], <span class="hljs-literal">true</span>);
table.AutoFilter.Apply();
table.AutoFilter.Columns[<span class="hljs-number">0</span>].ApplyFillColorFilter(Color.Red);</code></pre>
</div>
</div>
<p> In addition, our new APIs allow you to sort data across a filtered range (when auto-filter is enabled) and sort cells by their values/colors simultaneously (using sorting conditions). </p>
<p><a href="https://docs.devexpress.com/WindowsForms/17138/controls-and-libraries/spreadsheet/data-presentation/sorting?v=24.1#sort-range-by-color" target="_blank" rel="noopener">Documentation: Sort Cell Range by Color</a></p> <span
class="H-Separator"></span>
<h4 anchor="xtraspreadsheet-export-cell-range-to-svg">
<a name="xtraspreadsheet-export-cell-range-to-svg" class="anchor visible-anchor" href="#xtraspreadsheet-export-cell-range-to-svg">#</a>Export Cell Range to SVG
</h4>
<p> In this release, we enhanced our <a href="https://docs.devexpress.com/OfficeFileAPI/DevExpress.Spreadsheet.CellRangeExtensions.ExportToImage.overloads?v=24.1" target="_blank" rel="noopener">CellRangeExtensions.ExportToImage</a> method
and added support for the SVG image format. </p>
<div class="Attention">
<p class="sys-h-align-left"> The <code data-renderer="hljs" class="csharp" data-control="Code-Inline">CellRangeExtensions</code> class is defined in the DevExpress.Docs.v24.1.dll assembly. Add this assembly to your project or install
the DevExpress.Document.Processor NuGet Package to use <code data-renderer="hljs" class="csharp" data-control="Code-Inline">CellRangeExtensions</code> members. To use this class in production code, you will need an active
<a href="/products/net/office-file-api/#Pricing">DevExpress Office File API</a> or <a href="/buy">DevExpress Universal Subscription</a>. </p>
</div>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">C#</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="csharp">spreadsheetControl.LoadDocument(<span class="hljs-string">"InvestmentPortfolio.xlsx"</span>, DocumentFormat.Xlsx);
Worksheet worksheet = spreadsheetControl.ActiveWorksheet;
worksheet.Range[<span class="hljs-string">"B18:I30"</span>].ExportToImage(<span class="hljs-string">"cell_range_image.svg"</span>, ImageFileFormat.Svg);</code></pre>
</div>
</div>
<p> SVG Export is also available from the user interface - open the Print Preview dialog, click the Export to Image button, choose the SVG format in the Image Options dialog and complete document export. </p> <span
class="H-Separator"></span>
<h3 data-anchor="winforms-accessibility" data-toc-title="Accessibility and UI Automation">
<a name="winforms-accessibility" class="anchor"></a>Accessibility and UI Automation
</h3>
<h4 anchor="winforms-accessible-keyboard-nav">
<a name="winforms-accessible-keyboard-nav" class="anchor visible-anchor" href="#winforms-accessible-keyboard-nav">#</a>Accessible Keyboard Navigation
</h4>
<p><strong>TabPane & NavigationPane</strong></p>
<p> We added keyboard navigation support to our WinForms TabPane and Navigation Pane controls (much like that of the XtraTabControl). Keyboard focus is now managed as follows: </p>
<ul>
<li><code data-renderer="hljs" class="csharp" data-control="Code-Inline">Right</code>/<code data-renderer="hljs" class="csharp" data-control="Code-Inline">Left Arrow</code> — Activates the Next/Previous page.</li>
<li><code data-renderer="hljs" class="csharp" data-control="Code-Inline">Ctrl</code>+<code data-renderer="hljs" class="csharp" data-control="Code-Inline">Tab</code> / <code data-renderer="hljs" class="csharp"
data-control="Code-Inline">Ctrl</code>+<code data-renderer="hljs" class="csharp" data-control="Code-Inline">Shift</code>+<code data-renderer="hljs" class="csharp" data-control="Code-Inline">Tab</code> — Activates the Next/Previous
page and focuses the tab header or UI control displayed on the page.</li>
<li><code data-renderer="hljs" class="csharp" data-control="Code-Inline">Home</code> — Activates the first page.</li>
<li><code data-renderer="hljs" class="csharp" data-control="Code-Inline">End</code> — Activates the last page.</li>
</ul>
<p> Additional API includes: </p>
<ul>
<li><code data-renderer="hljs" class="csharp" data-control="Code-Inline">AllowNavigationThroughPages</code> — Activate this option to focus the tab header (rather than the UI control displayed on the page) when the user navigates using
the Tab key. This option is disabled by default.</li>
<li><code data-renderer="hljs" class="csharp" data-control="Code-Inline">ShowHeaderFocus</code> — Displays/hides the focus rectangle.</li>
</ul>
<p><strong>TextBox-based Data Editors in BarEditItems</strong></p>
<p> We improved keyboard navigation within our Ribbon UI and Toolbars. Keyboard focus is now appropriately managed to mimic behaviors found in Microsoft Word. Specifically, when the BarEditItem has focus and the user presses an arrow key,
the BarEditItem retains focus, allowing navigation within the editor. </p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-winforms-ribbon-edititem-border-wxi.png"
srcset="/subscriptions/i/24.1/24-1-winforms-ribbon-edititem-border-wxi.png 1x, /subscriptions/i/24.1/24-1-winforms-ribbon-edititem-border-wxi@2x.png 2x" alt="WinForms Ribbon in WXI Skin, DevExpress" width="630" height="174"
style="border: none" id="ctl00_ctl00_Content_Content_ctl1335"></div>
<p> v24.1 exposes new properties that allow you to suppress a keyboard key (<code data-renderer="hljs" class="csharp" data-control="Code-Inline">Alt</code> or <code data-renderer="hljs" class="csharp"
data-control="Code-Inline">Control</code>) for bar items with embedded editors (BarEditItem): </p>
<ul>
<li><a href="https://docs.devexpress.com/WindowsForms/DevExpress.XtraBars.BarManager.SuppressModifierKey?v=24.1" target="_blank" rel="noopener">BarManager.SuppressModifierKey</a> — This global setting specifies the behavior for all
BarEditItems within the Form.</li>
<li><a href="https://docs.devexpress.com/WindowsForms/DevExpress.XtraBars.BarEditItem.SuppressModifierKey?v=24.1" target="_blank" rel="noopener">BarEditItem.SuppressModifierKey</a> — Specifies the behavior for a specific BarEditItem.
</li>
</ul>
<p> The following example activates MS Word-inspired behavior for a bar item with a combo box. Instead of using the <code data-renderer="hljs" class="csharp" data-control="Code-Inline">Alt</code>+<code data-renderer="hljs" class="csharp"
data-control="Code-Inline">DownArrow</code> combination to open the dropdown, the user simply needs to press <code data-renderer="hljs" class="csharp" data-control="Code-Inline">DownArrow</code>: </p>
<p></p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-winforms-ribbon-dropdown-items-keyboard-nav.gif"
srcset="/subscriptions/i/24.1/24-1-winforms-ribbon-dropdown-items-keyboard-nav.gif 1x, /subscriptions/i/24.1/24-1-winforms-ribbon-dropdown-items-keyboard-nav@2x.gif 2x"
alt="WinForms TextBox-based Data Editors in BarEditItems, DevExpress" width="578" height="162" style="border: none" id="ctl00_ctl00_Content_Content_ctl1352"></div>
<p></p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">C#</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="csharp"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Form1</span>()</span> {
InitializeComponent();
barItemCombobox.SuppressModifierKey = DevExpress.XtraEditors.SuppressKeys.Alt;
}</code></pre>
</div>
</div>
<p><strong>ButtonEdit-based Editors</strong></p>
<p> We've optimized the keyboard focus within our ButtonEdit-related controls to ensure that it follows a logical and intuitive sequence. Users can easily tab from the edit box to buttons, navigate through buttons using <code
data-renderer="hljs" class="csharp" data-control="Code-Inline">Left</code>/<code data-renderer="hljs" class="csharp" data-control="Code-Inline">Right</code> keys, press buttons (<code data-renderer="hljs" class="csharp"
data-control="Code-Inline">Enter</code>/<code data-renderer="hljs" class="csharp" data-control="Code-Inline">Space</code>), and tab back to the edit box (<code data-renderer="hljs" class="csharp"
data-control="Code-Inline">Escape</code> or <code data-renderer="hljs" class="csharp" data-control="Code-Inline">Shift</code>+<code data-renderer="hljs" class="csharp" data-control="Code-Inline">Tab</code>). </p>
<p></p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-winforms-button-edit-keyboard-nav.gif"
srcset="/subscriptions/i/24.1/24-1-winforms-button-edit-keyboard-nav.gif 1x, /subscriptions/i/24.1/24-1-winforms-button-edit-keyboard-nav@2x.gif 2x" alt="WinForms ButtonEdit-based Editors - Keyboard Navigation, DevExpress" width="388"
height="286" style="border: none" id="ctl00_ctl00_Content_Content_ctl1374"></div>
<p></p>
<p> Use the <a href="https://docs.devexpress.com/WindowsForms/DevExpress.XtraEditors.KeyboardNavigationExtensions?v=24.1" target="_blank" rel="noopener">WindowsFormsSettings.KeyboardNavigationExtension</a> property to enable this behavior
for DevExpress TabPane, NavigationPane, and all ButtonEdit controls within the application. </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">C#</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="csharp"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Form1</span>()</span> {
InitializeComponent();
DevExpress.XtraEditors.WindowsFormsSettings.KeyboardNavigationExtensions = DevExpress.XtraEditors.KeyboardNavigationExtensions.All;
}</code></pre>
</div>
</div>
<p> Use the <a href="https://docs.devexpress.com/WindowsForms/DevExpress.XtraEditors.Repository.RepositoryItemButtonEdit.AllowButtonNavigation?v=24.1" target="_blank" rel="noopener">AllowButtonNavigation</a> property to enable keyboard
navigation for a specific ButtonEdit control. </p>
<p> Additional options include: </p>
<ul>
<li>In-place Mode Support</li>
<li>Right to Left Mode Support</li>
<li>Advanced Mode Support</li>
</ul>
<p><strong>WinForms TileView (Kanban)</strong></p>
<p> End-users can now focus tile group header/footer buttons with the keyboard and use arrow keys for left/right navigation. </p>
<p><strong>WinForms Diagram Control</strong></p>
<p> We improved keyboard navigation in the DevExpress WinForms Diagram control. Users can now use the following keyboard keys: </p>
<ul>
<li><code data-renderer="hljs" class="csharp" data-control="Code-Inline">Ctrl</code>+<code data-renderer="hljs" class="csharp" data-control="Code-Inline">+</code> – Zooms in on the canvas.</li>
<li><code data-renderer="hljs" class="csharp" data-control="Code-Inline">Ctrl</code>+<code data-renderer="hljs" class="csharp" data-control="Code-Inline">-</code> – Zooms out the canvas.</li>
<li><code data-renderer="hljs" class="csharp" data-control="Code-Inline">Ctrl</code>+<code data-renderer="hljs" class="csharp" data-control="Code-Inline">Space</code> – Expands/collapses the focused container.</li>
<li><code data-renderer="hljs" class="csharp" data-control="Code-Inline">F4</code> – Opens the Properties window.</li>
</ul>
<p><strong>Column Filter Popup</strong></p>
<p> When a user opens an Excel Filter Popup, the popup window automatically receives focus. Users can navigate between popup window UI elements using the keyboard. </p> <span class="H-Separator"></span>
<h4 anchor="winforms-accessibility-screen-readers">
<a name="winforms-accessibility-screen-readers" class="anchor visible-anchor" href="#winforms-accessibility-screen-readers">#</a>Screen Reader Related Enhancements
</h4>
<p> v24.1 ships with improved accessibility across our WinForms UI control library. Screen readers (such as Narrator and NVDA) can now pronounce the following user actions and properties: </p>
<ul>
<li>Checking an item in the Data Grid Column Customization Menu.</li>
<li>Expanding/collapsing an item in the DevExpress Accordion Control.</li>
<li>Specifying criteria within the DevExpress Grid Auto Filter Row.</li>
<li>Focusing tokens in the Token Editor (a Screen reader pronounces tokes).</li>
<li>Focusing a group in the DevExpress WinExplorer View.</li>
<li>Focusing a cell in the DevExpress Grid New Item Row.</li>
<li>Navigating through card fields in the DevExpress CardView.</li>
<li><a href="https://docs.devexpress.com/WindowsForms/DevExpress.XtraEditors.TextEditAdvancedModeOptions.Label" target="_blank" rel="noopener">TextEdit.Properties.AdvancedModeOptions.Label</a></li>
<li><a href="https://docs.devexpress.com/WindowsForms/DevExpress.XtraEditors.Repository.RepositoryItemTextEdit.NullValuePrompt" target="_blank" rel="noopener">TextEdit.Properties.NullValuePrompt</a></li>
</ul>
<p>Additional enhancements:</p>
<ul>
<li>
<p>When a user enters an incorrect expression in the Expression Editor, the screen reader pronounces the error message.</p>
<p></p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-winforms-exression-editor-with-error.png"
srcset="/subscriptions/i/24.1/24-1-winforms-exression-editor-with-error.png 1x, /subscriptions/i/24.1/24-1-winforms-exression-editor-with-error@2x.png 2x" alt="WinForms Expression Editor, DevExpress" style="border: none"
id="ctl00_ctl00_Content_Content_ctl2078"></div>
<p></p>
</li>
<li>
<p> When a user uses the integrated Find Panel to search for specific information, the screen reader pronounces the number of search results. </p>
<p></p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-winforms-find-panel.png" srcset="/subscriptions/i/24.1/24-1-winforms-find-panel.png 1x, /subscriptions/i/24.1/24-1-winforms-find-panel@2x.png 2x"
alt="Find Panel - WinForms Data Grid, DevExpress" width="694" height="322" style="border: none" id="ctl00_ctl00_Content_Content_ctl2083"></div>
<p></p>
</li>
</ul> <span class="H-Separator"></span>
<h4 anchor="winforms-accessibility-ribbon-bars">
<a name="winforms-accessibility-ribbon-bars" class="anchor visible-anchor" href="#winforms-accessibility-ribbon-bars">#</a>AccessKey and AcceleratorKey Support in Ribbon UI and Toolbars
</h4>
<p> Ribbon UI elements (Bar items, Ribbon pages, BackStageView, Group Caption button, and Application button) now expose the following accessibility-related properties: </p>
<ul>
<li><code data-renderer="hljs" class="csharp" data-control="Code-Inline">AccessKey</code> in MSAA and UI Automation</li>
<li><code data-renderer="hljs" class="csharp" data-control="Code-Inline">AcceleratorKey</code> in UI Automation.</li>
</ul>
<p><strong>Note</strong>: We set these properties based on values of properties such as ItemShortcut. </p> <span class="H-Separator"></span>
<h3 data-anchor="winforms-misc" data-toc-title="Miscellaneous Enhancements">
<a name="winforms-misc" class="anchor"></a>Miscellaneous Enhancements
</h3>
<h4 anchor="winforms-image-keyname">
<a name="winforms-image-keyname" class="anchor visible-anchor" href="#winforms-image-keyname">#</a>Assign Images by Key/Name
</h4>
<p> Image options include a new <code data-renderer="hljs" class="csharp" data-control="Code-Inline">ImageKey</code> string setting. Use it to specify an image by its "name". Unlike <code data-renderer="hljs" class="csharp"
data-control="Code-Inline">ImageIndex</code>, where adding or removing images can change the position of existing images in the collection (requiring the <code data-renderer="hljs" class="csharp"
data-control="Code-Inline">ImageIndex</code> property to be updated), the <code data-renderer="hljs" class="csharp" data-control="Code-Inline">ImageKey</code> property identifies an image regardless of its position in the collection
(search in the collection is done by the image name). </p>
<p><strong>Note</strong>: <code data-renderer="hljs" class="csharp" data-control="Code-Inline">ImageKey</code> takes priority over <code data-renderer="hljs" class="csharp" data-control="Code-Inline">ImageIndex</code> (if both properties
are specified). </p> <span class="H-Separator"></span>
<h3 data-anchor="winforms-performance" data-toc-title="Performance Improvements">
<a name="winforms-performance" class="anchor"></a>Performance Improvements
</h3>
<h4 anchor="winforms-out-of-process-designer">
<a name="winforms-out-of-process-designer" class="anchor visible-anchor" href="#winforms-out-of-process-designer">#</a>Improved Windows Forms Out-of-Process Designer
</h4>
<p> We were in close collaboration with the Microsoft dev team over the last few months, and Microsoft has recently released a Visual Studio 2022 update, which improves form load performance across a number of .NET Core / .NET usage
scenarios. </p>
<p> These performance enhancements are not tied to any DevExpress version because they are implemented at the Visual Studio core level (based on our feedback associated with problematic internal routines). From Microsoft
<a href="https://learn.microsoft.com/en-us/visualstudio/releases/2022/release-notes#performance-improvements-in-windows-forms-out-of-process-designer" target="_blank" rel="noopener">release notes</a>: </p>
<div class="Attention">
<p class="sys-h-align-left"> Through a fruitful collaboration with a key partner, we are thrilled to announce substantial enhancements to the WinForms server process <code data-renderer="hljs" class="csharp"
data-control="Code-Inline">TypeResolutionService</code>. These enhancements have yielded remarkable design time performance improvements, ranging from 30% to an impressive 50% in typical line of business applications. Notably, these
enhancements particularly shine during scenarios that trigger server process restart and designer reload, such as project rebuilds or adjustments in project references. </p>
<p class="sys-h-align-left"> At the heart of these performance improvements lies a new mechanism implemented by our team, prioritizing assemblies crucial for designer load. We encourage you to explore the updated designer and share your
invaluable feedback through <a href="https://developercommunity.visualstudio.com/VisualStudio" target="_blank" rel="noopener">VS Feedback channel</a> so that we can continue improving WinForms designer performance. </p>
</div>
<p> You can cut an additional 1-2 seconds from designer startup (if you do not need all DevExpress WinForms components simultaneously on your forms) by using the following smaller packages (like DevExpress.Win.Grid,
DevExpress.Win.TreeList, DevExpress.Win.Charts, etc.) instead of the large <strong>DevExpress.Win.Design</strong> package. </p>
<p><a href="https://community.devexpress.com/blogs/winforms/archive/2024/03/18/winforms-performance-enhancements-in-the-microsoft-winforms-designer-for-net-6-development.aspx" target="_blank" rel="noopener">Read the Blog Post</a></p>
<span class="H-Separator"></span>
<h3 data-anchor="winforms-survey" data-toc-title="Survey - WinForms">
<a name="winforms-survey" class="anchor"></a>Survey - WinForms
</h3>
<h4 anchor=""> Your Feedback Matters! </h4>
<div id="ctl00_ctl00_Content_Content_SurveyContainer" data-control="survey" class="InlineSurvey">
<div data-role="SurveyContent" data-markdown="false" data-partial="false" data-multiple-results="None" data-survey-id="518dac1e-2c9f-4594-a341-2060a68a020e" data-auth-required="true"
data-user-data="{"IsLoggedIn":false,"IsEmployee":false,"CustomerId":null}" style="display: none;">
</div>
<div data-role="AuthRequired" style="display: block;"> Please <a href="https://www.devexpress.com/MyAccount/LogIn/?returnUrl=https%3a%2f%2fwww.devexpress.com%2fsubscriptions%2fwhats-new%2f">login</a> to complete the survey. </div>
<div data-role="Loading" style="display: none;">
<img src="../../Content/Editors/ajax-loader.gif" style="border-width:0px;">
</div>
<div data-role="Completed" style="display: none;">
<h3> Survey Completed </h3>
<p class="sys-max-width-md-80 sys-max-width-lg-60">Thank you for taking the time to complete this survey. Your responses have now been posted. If you want to follow up with additional information, feel free to send us an email at
<a href="mailto:clientservices@devexpress.com">clientservices@devexpress.com</a> anytime. </p>
</div>
<div data-role="AlreadyPassed" style="display: none;">
<h3> You've Already Completed This Survey </h3>
<p class="sys-max-width-md-80 sys-max-width-lg-60">Our records show that you have already completed this survey. If you want to follow up with additional information, send us an email at
<a href="mailto:clientservices@devexpress.com">clientservices@devexpress.com</a>.</p>
</div>
<div data-role="Expired" style="display: none;">
<h3> This survey has expired </h3>
<p>If you want to share your feedback or request new functionality, please submit a new support ticket via the <a href="https://supportcenter.devexpress.com/">DevExpress Support Center</a>. We’ll be happy to follow up.</p>
</div>
</div>
<h2 class="SectionHeader" data-anchor="wpf" data-toc-title="WPF">
<a data-whatsnew-platform="wpf" name="wpf" class="anchor"></a>WPF Controls v24.1
</h2>
<div class="WhatsNewTOC grid sys-visibility-hidden sys-visibility-hidden sys-visibility-sm-shown">
<div class="row">
<div class="col-sm-6 col-md-3 col-order-1">
<p><a href="#wpf-accessibility"><span>Accessibility and UI Automation</span></a></p>
<p><a href="#wpf-dateonly-support"><span>DateOnly & TimeOnly Type Support</span></a></p>
<p><a href="#dxgrid"><span>Data Grid</span></a></p>
</div>
<div class="col-sm-6 col-md-3 col-sm-order-3 col-md-order-2">
<p><a href="#wpf-font-icon-images"><span>Font Icon Images</span></a></p>
<p><a href="#dxribbon"><span>Ribbon & Bars</span></a></p>
<p><a href="#dxpdfviewer"><span>PDF Viewer</span></a></p>
</div>
<div class="column-break sm">
</div>
<div class="col-sm-6 col-md-3 col-sm-order-2 col-md-order-3">
<p><a href="#dxrichtextedit"><span>Rich Text Editor</span></a></p>
<p><a href="#dxpropertygrid"><span>Property Grid</span></a></p>
<p><a href="#dxspreadsheet"><span>Spreadsheet</span></a></p>
</div>
<div class="col-sm-6 col-md-3 col-order-4">
<p><a href="#dxthemes"><span>Lightweight Themes</span></a></p>
<p><a href="#wpf-survey"><span>Survey - WPF</span></a></p>
</div>
</div>
</div>
<div class="Attention">
<p><strong>Your feedback matters.</strong><br> Please, review the description of <strong>WPF</strong>-related features below and leave your feedback at the end of the section. </p>
<p><a href="#wpf-survey">Go to the survey now.</a></p>
</div>
<h3 data-anchor="wpf-accessibility" data-toc-title="Accessibility and UI Automation">
<a name="wpf-accessibility" class="anchor"></a>Accessibility and UI Automation
</h3>
<h4 anchor="wpf-assistive-technologies">
<a name="wpf-assistive-technologies" class="anchor visible-anchor" href="#wpf-assistive-technologies">#</a>Assistive Technologies (Screen Readers) – Compatibility Enhancements
</h4>
<p> We enhanced our WPF Accessibility Tree for the following UI controls (assistive technologies obtain the necessary information to help address WCAG accessibility guidelines): </p>
<ul>
<li>Layout Control</li>
<li>Tab Control</li>
<li>Ribbon Gallery</li>
<li>Built-in Dialogs and Forms (such as Column Filter Popup, Bars Customization Window).</li>
</ul>
<p> Screen readers (such as Narrator and NVDA) can now pronounce the following actions: </p>
<ul>
<li>The user selects a row/node with the keyboard in the DevExpress WPF Grid or WPF TreeList control.</li>
<li>The user expands/collapses a node.</li>
<li>The user checks/unchecks a node.</li>
<li>The user moves focus to a WPF Ribbon Bar item.</li>
<li>The WPF Grid’s cell value is modified in code.</li>
</ul>
<p> Screen readers can now access the following information: </p>
<ul>
<li>Column/band name for the focused WPF Grid cell.</li>
<li>Focused WPF Grid row cell values in multi row selection mode.</li>
<li>The position of the focused cell among visible rows/columns.</li>
<li>The name of the New Item Row in DevExpress WPF Grid and TreeList controls.</li>
<li>Active cell editor type in the DevExpress WPF Grid.</li>
<li>DevExpress WPF ThemedMessageBox text.</li>
<li>DevExpress WPF Step Progress Bar items.</li>
</ul> <span class="H-Separator"></span>
<h4 anchor="wpf-accessible-keyboard-nav">
<a name="wpf-accessible-keyboard-nav" class="anchor visible-anchor" href="#wpf-accessible-keyboard-nav">#</a>Accessible Keyboard Navigation
</h4>
<p><strong>WPF Diagram Control</strong></p>
<p> We improved keyboard navigation in the DevExpress WPF Diagram control. Users can now use the following keyboard keys: </p>
<ul>
<li><code data-renderer="hljs" class="csharp" data-control="Code-Inline">Ctrl</code>+<code data-renderer="hljs" class="csharp" data-control="Code-Inline">+</code> – Zooms in on the canvas.</li>
<li><code data-renderer="hljs" class="csharp" data-control="Code-Inline">Ctrl</code>+<code data-renderer="hljs" class="csharp" data-control="Code-Inline">-</code> – Zooms out the canvas.</li>
<li><code data-renderer="hljs" class="csharp" data-control="Code-Inline">Ctrl</code>+<code data-renderer="hljs" class="csharp" data-control="Code-Inline">Space</code> – Expands/collapses the focused container.</li>
<li><code data-renderer="hljs" class="csharp" data-control="Code-Inline">F4</code> – Opens the Properties window.</li>
</ul>
<p><strong>WPF Ribbon Control</strong></p>
<p> We improved keyboard navigation within our WPF Ribbon control. Users can move focus to the "Expand/Collapse Ribbon" button using the <code data-renderer="hljs" class="csharp" data-control="Code-Inline">Tab</code> or <code
data-renderer="hljs" class="csharp" data-control="Code-Inline">Arrow</code> key (<code data-renderer="hljs" class="csharp" data-control="Code-Inline">Space</code> and <code data-renderer="hljs" class="csharp"
data-control="Code-Inline">Enter</code> keys expand/collapse the Ribbon). </p>
<p> v24.1 ships with improved keyboard navigation within BarSplitButtonItem: </p>
<ul>
<li><code data-renderer="hljs" class="csharp" data-control="Code-Inline">Enter</code> – Executes the main action.</li>
<li><code data-renderer="hljs" class="csharp" data-control="Code-Inline">Alt</code> + <code data-renderer="hljs" class="csharp" data-control="Code-Inline">DownArrow</code> – Invokes the drop-down window.</li>
</ul>
<p><strong>Row Context Menus in the WPF Grid Control</strong></p>
<p> Pressing the Context Menu Button invokes a context menu for the focused row. </p>
<p><strong>WPF Office Navigation Bar</strong></p>
<p> Users can now press <code data-renderer="hljs" class="csharp" data-control="Code-Inline">Space</code> or <code data-renderer="hljs" class="csharp" data-control="Code-Inline">Enter</code> to invoke an action associated with the focused
item. </p>
<p><strong>WPF Accordion Control</strong></p>
<p> Pressing the <code data-renderer="hljs" class="csharp" data-control="Code-Inline">Shift</code>+<code data-renderer="hljs" class="csharp" data-control="Code-Inline">Tab</code> shortcut focuses the "Expand/Collapse" button. </p>
<p><strong>WPF Track Bar Editor</strong></p>
<p> Users can now focus each thumb of the range track bar editor with the keyboard. </p> <span class="H-Separator"></span>
<h3 data-anchor="wpf-dateonly-support" data-toc-title="DateOnly & TimeOnly Type Support">
<a name="wpf-dateonly-support" class="anchor"></a>DateOnly & TimeOnly Type Support
</h3>
<p> DevExpress WPF Data Grid now supports <code data-renderer="hljs" class="csharp" data-control="Code-Inline">DateOnly</code> and <code data-renderer="hljs" class="csharp" data-control="Code-Inline">TimeOnly</code> data types (in .NET
applications). These data types offer the following advantages (versus the traditional DateTime type): usage clarity, improved database compatibility, less space during serialization, and the ability to mitigate potential
errors/inconsistencies related to different time zones. </p>
<p> Built-in DateOnly/TimeOnly support extends to: </p>
<ul>
<li>UI Elements Related to Data Filtering (Column Filter Popup, Filter Editor, Expression Editor, Automatic Filter Row)</li>
<li>Conditional Formatting Rules</li>
<li>Data Summaries</li>
<li>Data Grouping</li>
<li>Unbound Columns</li>
<li>Criteria Operators</li>
<li>Masks</li>
<li>Search</li>
</ul> <span class="H-Separator"></span>
<h3 data-anchor="dxgrid" data-toc-title="Data Grid">
<a name="dxgrid" class="anchor"></a>Data Grid
</h3>
<h4 anchor="dxgrid-export-cell-images">
<a name="dxgrid-export-cell-images" class="anchor visible-anchor" href="#dxgrid-export-cell-images">#</a>Export Cell Images to Excel
</h4>
<p> The WPF Data Grid now exports images (raster and SVG) displayed within cells of bound and unbound columns to XLSX format in
<a href="https://docs.devexpress.com/WPF/10018/controls-and-libraries/data-grid/printing-and-exporting/data-aware-export" target="_blank" rel="noopener">data-aware export mode</a>. Cell images are exported as a <code
data-renderer="hljs" class="csharp" data-control="Code-Inline">Byte[]</code> array. To activate this feature, set the
<a href="https://docs.devexpress.com/CoreLibraries/DevExpress.XtraPrinting.XlsxExportOptionsEx.AllowCellImages" target="_blank" rel="noopener">AllowCellImages</a> property to <code data-renderer="hljs" class="csharp"
data-control="Code-Inline">DefaultBoolean.True</code>. </p>
<p></p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-wpf-grid-export-cell-images-to-excel.png"
srcset="/subscriptions/i/24.1/24-1-wpf-grid-export-cell-images-to-excel.png 1x, /subscriptions/i/24.1/24-1-wpf-grid-export-cell-images-to-excel@2x.png 2x" alt="Export Cell Images to Excel - WPF Data Grid, DevExpress" width="637"
height="335" style="border: none" id="ctl00_ctl00_Content_Content_ctl2305"></div>
<p></p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">C#</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="csharp">XlsxExportOptionsEx options = <span class="hljs-keyword">new</span> XlsxExportOptionsEx();
options.AllowCellImages = DevExpress.Utils.DefaultBoolean.True;
view.ExportToXlsx(<span class="hljs-string">"grid_export.xlsx"</span>, options);
</code></pre>
</div>
</div>
<p> Handle the <a href="https://docs.devexpress.com/CoreLibraries/DevExpress.XtraPrinting.XlsxExportOptionsEx.CustomizeCell?v=24.1" target="_blank" rel="noopener">CustomizeCell</a> event to customize cell images or replace values with
images (based on export conditions) before the Grid Control generates the output document. </p>
<p><a href="https://docs.devexpress.com/CoreLibraries/DevExpress.XtraPrinting.XlsxExportOptionsEx.AllowCellImages?v=24.1#replace-cell-content-with-images" target="_blank" rel="noopener">Documentation</a></p> <span
class="H-Separator"></span>
<h4 anchor="dxgrid-filter-by-color-icons">
<a name="dxgrid-filter-by-color-icons" class="anchor visible-anchor" href="#dxgrid-filter-by-color-icons">#</a>Filter by Color and Icon Set
</h4>
<p> We extended the user experience when using the WPF Grid Control (in TableView and TreeListView). Users can quickly filter data based on visual criteria (Icon Set and Color Scale format conditions). This functionality is available to
users via the column header's context menu if conditional formatting is applied: </p>
<p></p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-wpf-grid-conditional-formatting.png"
srcset="/subscriptions/i/24.1/24-1-wpf-grid-conditional-formatting.png 1x, /subscriptions/i/24.1/24-1-wpf-grid-conditional-formatting@2x.png 2x" alt="Filter by Color and Icon Set - WPF Data Grid, DevExpress" width="720" height="471"
style="border: none" id="ctl00_ctl00_Content_Content_ctl2324"></div>
<p></p>
<p> New APIs include: </p>
<ul>
<li><a href="https://docs.devexpress.com/WPF/DevExpress.Xpf.Grid.TableView.AllowFormatConditionFiltersMenu?v=24.1" target="_blank" rel="noopener">TableView.AllowFormatConditionFiltersMenu</a> – Displays/hides the “Format Condition
Filters” submenu in context menus associated with all columns in a TableView (if conditional formatting is applied).</li>
<li><a href="https://docs.devexpress.com/WPF/DevExpress.Xpf.Grid.TreeListView.AllowFormatConditionFiltersMenu?v=24.1" target="_blank" rel="noopener">TreeListView.AllowFormatConditionFiltersMenu</a> – Displays/hides the “Format Condition
Filters” submenu in context menus associated with all columns in a TreeListView (if conditional formatting is applied).</li>
<li><a href="https://docs.devexpress.com/WPF/DevExpress.Xpf.Grid.ColumnBase.AllowFormatConditionFiltersMenu?v=24.1" target="_blank" rel="noopener">AllowFormatConditionFiltersMenu</a> – Displays/hides the “Format Condition Filters”
submenu in the context menu associated with a specific column (if conditional formatting is applied).</li>
</ul> <span class="H-Separator"></span>
<h4 anchor="dxfiltereditor-aggregate-filters">
<a name="dxfiltereditor-aggregate-filters" class="anchor visible-anchor" href="#dxfiltereditor-aggregate-filters">#</a>Aggregate Filters
</h4>
<p> We added aggregate filter support to our WPF Data Grid. The Data Grid exposes a new
<a href="https://docs.devexpress.com/WPF/DevExpress.Xpf.Grid.DataViewBase.AllowFilterEditorAggregateOperands?v=24.1" target="_blank" rel="noopener">AllowFilterEditorAggregateOperands</a> property that allows users to filter data by
items in bound collection data fields (for example, master-detail data). When enabled, the grid Filter Editor displays aggregated operands for collection properties/fields (SUM, COUNT, MIN, MAX, AVG, EXISTS). </p>
<p></p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-wpf-fitlereditor-aggregate-filters.png"
srcset="/subscriptions/i/24.1/24-1-wpf-fitlereditor-aggregate-filters.png 1x, /subscriptions/i/24.1/24-1-wpf-fitlereditor-aggregate-filters@2x.png 2x" alt="Aggregate Filters - WPF Filter Editor, DevExpress" width="500" height="350"
style="border: none" id="ctl00_ctl00_Content_Content_ctl2340"></div>
<p></p>
<p> You can also customize the operand list (for example, hide unnecessary operands) for specific data columns using the
<a href="https://docs.devexpress.com/WPF/DevExpress.Xpf.Grid.ColumnBase.AllowedAggregateFilters?v=24.1" target="_blank" rel="noopener">AllowedAggregateFilters</a> property. </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">XAML</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="XML"><span class="hljs-tag"><<span class="hljs-name">dxg:GridColumn</span> <span class="hljs-attr">FieldName</span>=<span class="hljs-string">"Genres"</span> <span class="hljs-attr">AllowedAggregateFilters</span>=<span class="hljs-string">"Exists, Count"</span>/></span></code></pre>
</div>
</div>
<p></p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-wpf-filtereditor-allowedaggregatefilters.png"
srcset="/subscriptions/i/24.1/24-1-wpf-filtereditor-allowedaggregatefilters.png 1x, /subscriptions/i/24.1/24-1-wpf-filtereditor-allowedaggregatefilters@2x.png 2x" alt="Aggregate Filters - WPF Data Grid, DevExpress" width="500"
height="350" style="border: none" id="ctl00_ctl00_Content_Content_ctl2348"></div>
<p></p> <span class="H-Separator"></span>
<h3 data-anchor="wpf-font-icon-images" data-toc-title="Font Icon Images">
<a name="wpf-font-icon-images" class="anchor"></a>Font Icon Images
</h3>
<p> Support for Font Icon Images was first introduced in our WinForms product line (Dec 2023). v24.1 extends this feature to our WPF UI library. </p>
<p> Use the DevExpress WPF Image Picker (integrated within Visual Studio) to assign font icon images to individual UI controls/elements or use our FontIconSource extension to do the same in code. </p> <p><img
src="/subscriptions/i/24.1/24-1-wpf-font-icons-images.png" srcset="/subscriptions/i/24.1/24-1-wpf-font-icons-images.png 1x, /subscriptions/i/24.1/24-1-wpf-font-icons-images@2x.png 2x"
alt="Font Icon Images - WPF UI Controls, DevExpress" width="850" height="691" style="border: none" id="ctl00_ctl00_Content_Content_ctl2360"></p> <p> If you execute a DevExpress-powered WPF application, it will display icons from
the most recent icon font available in the system. For example, the "Segoe Fluent Icons" font is used as the default font if both "Segoe Fluent Icons" and "Segoe MDL2 Assets" fonts are installed. </p>
<p> Use the <a href="https://docs.devexpress.com/WPF/DevExpress.Xpf.Core.FontIconSourceExtension.FontFamily?v=24.1" target="_blank" rel="noopener">FontIconSourceExtension.FontFamily</a> property to specify icon font: </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">XAML</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="XML"><span class="hljs-tag"><<span class="hljs-name">dxb:BarButtonItem</span> <span class="hljs-attr">Glyph</span>=<span class="hljs-string">"{dx:FontIconSource Glyph=0xf0b4, FontFamily=SegoeMDL2Assets}"</span>/></span></code></pre>
</div>
</div>
<p> You can also select an icon color from predefined values (Red, Green, Blue, Yellow, Black, and White). These colors are auto modified to match the applied DevExpress Theme: </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">XAML</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="XML"><span class="hljs-tag"><<span class="hljs-name">dxb:BarButtonItem</span> <span class="hljs-attr">Glyph</span>=<span class="hljs-string">"{dx:FontIconSource Glyph=59246, ColorName=Yellow}"</span>/></span></code></pre>
</div>
</div>
<p> And yes, you can use <a href="https://docs.devexpress.com/WPF/DevExpress.Xpf.Core.WpfSvgPalette?v=24.1" target="_blank" rel="noopener">WpfSvgPalette</a> to colorize icons to address design preferences: </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">XAML</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="XML"><span class="hljs-tag"><<span class="hljs-name">dxb:BarButtonItem</span> <span class="hljs-attr">Glyph</span>=<span class="hljs-string">"{dx:FontIconSource Glyph=59246}"</span>></span>
<span class="hljs-tag"><<span class="hljs-name">dx:WpfSvgPalette.Palette</span>></span>
<span class="hljs-tag"><<span class="hljs-name">dx:WpfSvgPalette</span>></span>
<span class="hljs-tag"><<span class="hljs-name">SolidColorBrush</span> <span class="hljs-attr">x:Key</span>=<span class="hljs-string">"Black"</span> <span class="hljs-attr">Color</span>=<span class="hljs-string">"Aqua"</span>/></span>
<span class="hljs-tag"></<span class="hljs-name">dx:WpfSvgPalette</span>></span>
<span class="hljs-tag"></<span class="hljs-name">dx:WpfSvgPalette.Palette</span>></span>
<span class="hljs-tag"></<span class="hljs-name">dxb:BarButtonItem</span>></span></code></pre>
</div>
</div>
<p><a href="https://docs.devexpress.com/WPF/404918/common-concepts/images/font-icon-images?v=24.1" target="_blank" rel="noopener">Documentation: Font Icon Images</a></p> <span class="H-Separator"></span>
<h3 data-anchor="dxribbon" data-toc-title="Ribbon & Bars">
<a name="dxribbon" class="anchor"></a>Ribbon & Bars
</h3>
<h4 anchor="dxribbon-searchbox">
<a name="dxribbon-searchbox" class="anchor visible-anchor" href="#dxribbon-searchbox">#</a>Search Box
</h4>
<p> A Ribbon-based UI can include dozens of commands across multiple pages. Without prior experience with a given app, users can struggle to locate appropriate actions/commands. To minimize usage friction/learning curve, v24.1 ships with
a new WPF Ribbon Search Box. </p>
<p></p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-wpf-ribbon-search.png" srcset="/subscriptions/i/24.1/24-1-wpf-ribbon-search.png 1x, /subscriptions/i/24.1/24-1-wpf-ribbon-search@2x.png 2x"
alt="Search Box - WPF Ribbon, DevExpress" width="959" height="373" style="border: none" id="ctl00_ctl00_Content_Content_ctl2394"></div>
<p></p>
<p> Specify the <a href="https://docs.devexpress.com/WPF/DevExpress.Xpf.Core.ThemedWindow.SearchItemDisplayMode?v=24.1" target="_blank" rel="noopener">SearchItemDisplayMode</a> property to activate the search box in your WPF app. Our WPF
Ribbon compares the search string to command content (<code data-renderer="hljs" class="csharp" data-control="Code-Inline">BarButtonItem.Content</code>) to generate search results. </p>
<p> You can enable an item's <a href="https://docs.devexpress.com/WPF/DevExpress.Xpf.Bars.BarItemSearchSettings.HideFromSearch?v=24.1" target="_blank" rel="noopener">HideFromSearch</a> option to exclude it from search. For more granular
control, use the following events: </p>
<ul>
<li><a href="https://docs.devexpress.com/WPF/DevExpress.Xpf.Core.ThemedWindow.ItemsRequested?v=24.1" target="_blank" rel="noopener">ItemsRequested</a> – Fires when the searchable items list is generated. The event allows you to modify
search results before applying the search criteria (for example, to add additional items based on a condition).</li>
<li><a href="https://docs.devexpress.com/WPF/DevExpress.Xpf.Core.ThemedWindow.ItemFiltering?v=24.1" target="_blank" rel="noopener">ItemFiltering</a> – Fires for each item before it is displayed in search results. The event allows you to
hide the item from search results.</li>
<li><a href="https://docs.devexpress.com/WPF/DevExpress.Xpf.Core.ThemedWindow.ItemsFiltered?v=24.1" target="_blank" rel="noopener">ItemsFiltered</a> – Notifies when a search is complete.</li>
</ul>
<p> Additional settings include: </p>
<ul>
<li><a href="https://docs.devexpress.com/WPF/DevExpress.Xpf.Core.ThemedWindow.SearchDelay?v=24.1" target="_blank" rel="noopener">SearchDelay</a> – Specifies the delay in milliseconds between the last text change and the text search.
</li>
<li><a href="https://docs.devexpress.com/WPF/DevExpress.Xpf.Core.ThemedWindow.SearchItemFocusShortcut?v=24.1" target="_blank" rel="noopener">SearchItemFocusShortcut</a> – Specifies the keyboard shortcut used to focus the search box (the
default shortcut is "Ctrl+F").</li>
<li><a href="https://docs.devexpress.com/WPF/DevExpress.Xpf.Core.ThemedWindow.ShowDescriptionInSearchResults?v=24.1" target="_blank" rel="noopener">ShowDescriptionInSearchResults</a> - Specifies whether to display the path to items
within the DevExpress WPF Ribbon UI (Category > Page > Group).</li>
</ul>
<div class="grid block-grid sys-max-width-lg-80 sys-visibility-hidden sys-visibility-hidden sys-visibility-sm-shown">
<div class="row">
<div class="col-sm-3">
<a href="dxdemo://Wpf/DXRibbon/MainDemo/" target="_blank" rel="noopener" class="Button Gray">
Run Demo
</a>
</div>
<div class="col-sm-9 sys-v-align-middle">
<span class="FootNote"> To execute this demo, you must first <br><a href="https://go.devexpress.com/DevexpressDownload_UniversalTrial.aspx" target="_blank" rel="noopener">
install the DevExpress WPF product library
</a>. </span>
</div>
</div>
</div> <span class="H-Separator"></span>
<h3 data-anchor="dxpdfviewer" data-toc-title="PDF Viewer">
<a name="dxpdfviewer" class="anchor"></a>PDF Viewer
</h3>
<h4 anchor="dxpdfviewer-signature-info-panel">
<a name="dxpdfviewer-signature-info-panel" class="anchor visible-anchor" href="#dxpdfviewer-signature-info-panel">#</a>Signature Info Panel
</h4>
<p> With our new <strong>Signature Info</strong> panel, you can display detailed information for each signature in the loaded document and verify signature validity. </p>
<p> When you open a document, the PDF Viewer verifies signatures and displays associated status in the Signature panel (valid, invalid, or unknown). </p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-wpf-pdfviewer-signature-info-panel.png"
srcset="/subscriptions/i/24.1/24-1-wpf-pdfviewer-signature-info-panel.png 1x, /subscriptions/i/24.1/24-1-wpf-pdfviewer-signature-info-panel@2x.png 2x" alt="Signature Info Panel - WPF PDF Viewer, DevExpress" width="609" height="474"
style="border: none" id="ctl00_ctl00_Content_Content_ctl2429"></div>
<p> In addition, the new panel displays the following signature-related information: </p>
<ul>
<li>Location of the signature in the document</li>
<li>Signer's information</li>
<li>Reasons the signature was created</li>
<li>Date and time when the document was singed and modified once it was signed</li>
<li>Certificate information.</li>
</ul>
<p><a href="https://docs.devexpress.com/WPF/117597/controls-and-libraries/pdf-viewer/visual-elements/navigation-pane?v=24.1#signatures" target="_blank" rel="noopener">Documentation</a></p> <span class="H-Separator"></span>
<h4 anchor="dxpdfviewer-layers">
<a name="dxpdfviewer-layers" class="anchor visible-anchor" href="#dxpdfviewer-layers">#</a>Layers
</h4>
<p> PDF document layers allow you to selectively view or hide specific content sections. The main purpose of layers is to control the visibility of graphics objects rendered in a PDF document across different states (when you view or
print a PDF document). </p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-wpf-pdfviewer-layers.png" srcset="/subscriptions/i/24.1/24-1-wpf-pdfviewer-layers.png 1x, /subscriptions/i/24.1/24-1-wpf-pdfviewer-layers@2x.png 2x"
alt="Layers - WPF PDF Viewer, DevExpress" width="870" height="448" style="border: none" id="ctl00_ctl00_Content_Content_ctl2444"></div>
<p> We added a <strong>Layers</strong> panel to display all layers contained in a document. This new capability allows you to change layer visibility via the UI. Click the check box next to the layer's name in the new Layers panel to
display/hide a given document layer. Visible layers are highlighted using an “eye” icon; layers that cannot be hidden because of a document configuration do not have a check box next to their name. </p>
<p> With the power of the <strong>PDF Facade API</strong>, you can also access and manage layer visibility at runtime when you preview or print your PDF documents. Call the
<a href="https://docs.devexpress.com/OfficeFileAPI/DevExpress.Pdf.PdfViewerExtensions.GetDocumentFacade(DevExpress.Pdf.IPdfViewer)?v=24.1" target="_blank" rel="noopener">PdfViewerExtensions.GetDocumentFacade</a> extension method to
obtain the PdfDocumentFacade class object (it allows you to change the PDF document without access to its inner structure) and use the
<a href="https://docs.devexpress.com/OfficeFileAPI/DevExpress.Pdf.PdfDocumentFacade.OptionalContentVisibility?v=24.1" target="_blank" rel="noopener">PdfDocumentFacade.OptionalContentVisibility</a> collection to change the visibility
state for the required document layers in code. </p>
<div class="Attention">
<p class="sys-h-align-left"> The <code data-renderer="hljs" class="csharp" data-control="Code-Inline">PdfDocumentFacade</code> class is defined in the DevExpress.Docs.v24.1.dll assembly. Add this assembly to your project or install the
DevExpress.Document.Processor NuGet Package to use the <code data-renderer="hljs" class="csharp" data-control="Code-Inline">PdfDocumentFacade</code> members. You need a license for the
<a href="/products/net/office-file-api/#Pricing">DevExpress Office File API Subscription</a> or <a href="/buy">DevExpress Universal Subscription</a> to use this class in production code. </p>
</div>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">C#</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="csharp">pdfViewer.LoadDocument(<span class="hljs-string">"layers.pdf"</span>);
PdfDocumentFacade documentFacade = pdfViewer.GetDocumentFacade();
<span class="hljs-comment">// Set visibility for each Layer</span>
documentFacade.OptionalContentVisibility.Groups[<span class="hljs-number">0</span>].Visible = <span class="hljs-literal">false</span>;
documentFacade.OptionalContentVisibility.Groups[<span class="hljs-number">1</span>].Visible = <span class="hljs-literal">false</span>;
documentFacade.OptionalContentVisibility.Groups[<span class="hljs-number">2</span>].Visible = <span class="hljs-literal">true</span>;</code></pre>
</div>
</div>
<p><a href="https://docs.devexpress.com/WPF/404952/controls-and-libraries/pdf-viewer/additional-content/layers?v=24.1" target="_blank" rel="noopener">Documentation</a></p> <span class="H-Separator"></span>
<h3 data-anchor="dxrichtextedit" data-toc-title="Rich Text Editor">
<a name="dxrichtextedit" class="anchor"></a>Rich Text Editor
</h3>
<h4 anchor="dxrichtextedit-export-to-accessible-pdf">
<a name="dxrichtextedit-export-to-accessible-pdf" class="anchor visible-anchor" href="#dxrichtextedit-export-to-accessible-pdf">#</a>Export to Accessible PDF
</h4>
<p> We extended accessibility-related support to the following elements when exporting Word documents to accessible PDF files: </p>
<ul>
<li>Table of Contents tagging</li>
<li>Metadata fields</li>
<li>Alt text handling</li>
<li>Tables</li>
<li>Floating objects.</li>
</ul>
<p> Adobe Acrobat Pro and PDF Accessibility Checker 2024 were used for quality control. Our test documents successfully passed validation for PDF/UA compatibility and WCAG 2.1 compliance. </p>
<p> Accessibility-related export enhancements are available out-of-the-box when you specify the <code data-renderer="hljs" class="csharp" data-control="Code-Inline">PdfUACompatibility</code> option: </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">C#</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="csharp"><span class="hljs-keyword">using</span> System.IO;
<span class="hljs-keyword">using</span> DevExpress.XtraRichEdit;
<span class="hljs-comment">//...</span>
<span class="hljs-keyword">using</span>(FileStream stream =
<span class="hljs-keyword">new</span> FileStream(resultFilePath, FileMode.Create, FileAccess.Write, FileShare.Read)) {
PdfExportOptions exportOptions = <span class="hljs-keyword">new</span> PdfExportOptions();
exportOptions.PdfUACompatibility = PdfUACompatibility.PdfUA1;
richEditControl.ExportToPdf(stream, exportOptions);
}</code></pre>
</div>
</div> <span class="H-Separator"></span>
<h4 anchor="dxrichtextedit-decorative-shapes">
<a name="dxrichtextedit-decorative-shapes" class="anchor visible-anchor" href="#dxrichtextedit-decorative-shapes">#</a>Decorative Shapes
</h4>
<p> We added a <code data-renderer="hljs" class="csharp" data-control="Code-Inline">Decorative</code> property for the
<a href="https://docs.devexpress.com/OfficeFileAPI/DevExpress.XtraRichEdit.API.Native.DrawingObject.Decorative?v=24.1" target="_blank" rel="noopener">Shape</a> class to mark document graphics (pictures, shapes, and charts) as
decorative. Decorative shapes add visual interest, but they are not informative. Thus, you do not need to specify Alt Text (meaningful description) for decorative objects when you generate an accessible document. </p> <span
class="H-Separator"></span>
<h4 anchor="dxrichtextedit-math-equations">
<a name="dxrichtextedit-math-equations" class="anchor visible-anchor" href="#dxrichtextedit-math-equations">#</a>Math Equations
</h4>
<p> Our Rich Text Editor now preserves Math Equations when saving a document. You can import your Word documents with Math Equations in our WinForms Rich Text Editor and save them to the RTF and OpenXml (.docx/.docm) formats without
content loss. </p>
<p><strong>Note</strong>: Math Equations will be printed or exported to PDF only if the source document contains a fallback image for a Math Equation. To suppress Math Equation import, set the
<a href="https://docs.devexpress.com/OfficeFileAPI/DevExpress.XtraRichEdit.DocumentCapabilitiesOptions.MathEquations?v=24.1" target="_blank" rel="noopener">DocumentCapabilities.MathEquations</a> property to <code data-renderer="hljs"
class="csharp" data-control="Code-Inline">DocumentCapability.Disabled</code>. </p> <span class="H-Separator"></span>
<h4 anchor="dxrichtextedit-gutter-mirrored-margins">
<a name="dxrichtextedit-gutter-mirrored-margins" class="anchor visible-anchor" href="#dxrichtextedit-gutter-mirrored-margins">#</a>Gutter and Mirrored Margins
</h4>
<p> The DevExpress WPF Rich Text Editor v24.1 allows you to specify gutter margins - extra space that ensures binding will not obscure text on printed pages. You can specify gutter position (top, left, and right) and margin size. Use the
<a href="https://docs.devexpress.com/OfficeFileAPI/DevExpress.XtraRichEdit.API.Native.Document.GutterAtTop?v=24.1" target="_blank" rel="noopener">Document.GutterAtTop</a>,
<a href="https://docs.devexpress.com/OfficeFileAPI/DevExpress.XtraRichEdit.API.Native.SectionMargins.GutterPosition?v=24.1" target="_blank" rel="noopener">SectionMargins.GutterPosition</a>, and
<a href="https://docs.devexpress.com/OfficeFileAPI/DevExpress.XtraRichEdit.API.Native.SectionMargins.Gutter?v=24.1" target="_blank" rel="noopener">SectionMargins.Gutter</a> properties to address specific usage requirements. </p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-wpf-richtexteditor-gutter-and-mirrored-margins.png"
srcset="/subscriptions/i/24.1/24-1-wpf-richtexteditor-gutter-and-mirrored-margins.png 1x, /subscriptions/i/24.1/24-1-wpf-richtexteditor-gutter-and-mirrored-margins@2x.png 2x"
alt="Gutter and Mirrored Margins - WPF Rich Text Editor, DevExpress" width="436" height="432" style="border: none" id="ctl00_ctl00_Content_Content_ctl2544"></div>
<p> The following code snippet adds a left gutter to the first document section: </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">C#</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="csharp"><span class="hljs-keyword">using</span> DevExpress.XtraRichEdit;
<span class="hljs-keyword">using</span> DevExpress.XtraRichEdit.API.Native;
<span class="hljs-keyword">using</span> DevExpress.Office.Utils;
<span class="hljs-comment">//...</span>
richEditControl.LoadDocument(<span class="hljs-string">@"Documents//Alice.docx"</span>);
Document document = richEditControl.Document;
Section firstSection = wordProcessor.Document.Sections[<span class="hljs-number">0</span>];
<span class="hljs-keyword">var</span> pageMargins = firstSection.Margins;
pageMargins.GutterPosition = GutterPosition.Left;
pageMargins.Gutter = Units.InchesToDocumentsF(<span class="hljs-number">1</span>);
richEditControl.SaveDocument(<span class="hljs-string">"Alice_formatted.docx"</span>, DocumentFormat.OpenXml);</code></pre>
</div>
</div>
<p> Our new <a href="https://docs.devexpress.com/OfficeFileAPI/DevExpress.XtraRichEdit.API.Native.Document.MarginType?v=24.1" target="_blank" rel="noopener">Document.MarginType</a> property allows you to define a regular or mirrored
margin type. Enable mirrored margins if you print on both sides of the paper and want to bind the printout. </p>
<p> The following code snippet enables mirrored margins and specifies an additional space value: </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">C#</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="csharp"><span class="hljs-keyword">using</span> DevExpress.XtraRichEdit;
<span class="hljs-keyword">using</span> DevExpress.XtraRichEdit.API.Native;
<span class="hljs-keyword">using</span> DevExpress.Office.Utils;
<span class="hljs-comment">//...</span>
richEditControl.LoadDocument(<span class="hljs-string">@"Documents//Alice.docx"</span>);
Document document = richEditControl.Document;
<span class="hljs-comment">// Enable mirrored margins</span>
document.MarginsType = MarginsType.Mirrored;
<span class="hljs-keyword">foreach</span> (Section section <span class="hljs-keyword">in</span> richEditControl.Document.Sections) {
<span class="hljs-keyword">var</span> pageMargins = section.Margins;
<span class="hljs-comment">// Set the value for mirrored margins</span>
pageMargins.Gutter = Units.InchesToDocumentsF(<span class="hljs-number">0.5f</span>);
}
richEditControl.SaveDocument(<span class="hljs-string">"Alice_formatted.docx"</span>, DocumentFormat.OpenXml);</code></pre>
</div>
</div>
<p> New UI elements are also available. </p>
<p><a href="https://docs.devexpress.com/WPF/9116/controls-and-libraries/rich-text-editor/rich-edit-control-document/sections?v=24.1#add-gutter-margins" target="_blank" rel="noopener">Documentation</a></p> <span
class="H-Separator"></span>
<h4 anchor="dxrichtextedit-image-export-api">
<a name="dxrichtextedit-image-export-api" class="anchor visible-anchor" href="#dxrichtextedit-image-export-api">#</a>Image Export API
</h4>
<p> v24.1 includes new cross-platform APIs to export Word document pages to an image. This new capability allows you to generate document previews. With our new APIs, you can convert document pages to raster and vector images (PNG, JPEG,
BMP, multi-page Tiff, emf), save them as physical files on the disk or obtain a list of image streams for further processing in code. You can also set image background color, modify output image resolution, or generate thumbnail images
with a specified size. </p>
<p> The new API is available via the
<a href="https://docs.devexpress.com/OfficeFileAPI/DevExpress.XtraRichEdit.RichEditDocumentServerExtensions.ExportToImage.overloads?v=24.1" target="_blank" rel="noopener">RichEditDocumentServerExtensions.ExportToImage</a> extension
method of the <code data-renderer="hljs" class="csharp" data-control="Code-Inline">Document</code> object. </p>
<div class="Attention">
<p class="sys-h-align-left"> Please note that the <code data-renderer="hljs" class="csharp" data-control="Code-Inline">RichEditDocumentServerExtensions</code> class is defined in the DevExpress.Docs.v24.1.dll assembly. Add this assembly
to your project or install the "DevExpress.Document.Processor" NuGet Package to use the <code data-renderer="hljs" class="csharp" data-control="Code-Inline">RichEditDocumentServerExtensions</code> members. You need a license for the
<a href="/products/net/office-file-api/#Pricing">DevExpress Office File API Subscription</a> or <a href="/buy">DevExpress Universal Subscription</a> to use this class in production code. </p>
</div>
<p> The following code snippet exports the first document page to an image with a specified size and JPEG format: </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">C#</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="csharp"><span class="hljs-keyword">using</span> DevExpress.XtraRichEdit;
<span class="hljs-keyword">using</span> DevExpress.XtraRichEdit.Export.Image;
<span class="hljs-keyword">using</span> DevExpress.Drawing;
richEditControl.LoadDocument(<span class="hljs-string">@"C:\Documents\Alice.docx"</span>);
<span class="hljs-comment">//...</span>
RichEditImageExportOptions options = <span class="hljs-keyword">new</span> RichEditImageExportOptions();
options.Format = DXImageFormat.Jpeg;
options.PageRange = <span class="hljs-string">"1"</span>;
options.LargestEdgeLength = <span class="hljs-number">1080</span>;
richEditControl.Document.ExportToImage(<span class="hljs-string">@"C:\Documents\Image.jpeg"</span>, options);</code></pre>
</div>
</div> <span class="H-Separator"></span>
<h4 anchor="dxrichtextedit-export-pages-to-svg">
<a name="dxrichtextedit-export-pages-to-svg" class="anchor visible-anchor" href="#dxrichtextedit-export-pages-to-svg">#</a>Export Document Pages to SVG
</h4>
<p> Our new Image Export APIs allow you to export document pages to SVG. Use the <code data-renderer="hljs" class="csharp" data-control="Code-Inline">RichEditImageExportOptions.Format</code> option to set SVG as a target image format.
</p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">C#</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="csharp">RichEditImageExportOptions options = <span class="hljs-keyword">new</span> RichEditImageExportOptions();
options.Format = DXImageFormat.Svg;
options.PageRange = <span class="hljs-string">"1"</span>;
richEditControl.Document.ExportToImage(<span class="hljs-string">@"C:\Documents\Image.svg"</span>, options);</code></pre>
</div>
</div>
<p> SVG Export is also available from the user interface - open the Print Preview dialog, click the Export to Image button, choose the SVG format in the Image Options dialog and complete document export. </p> <span
class="H-Separator"></span>
<h3 data-anchor="dxpropertygrid" data-toc-title="Property Grid">
<a name="dxpropertygrid" class="anchor"></a>Property Grid
</h3>
<h4 anchor="dxpropertygrid-customize-row-appearance">
<a name="dxpropertygrid-customize-row-appearance" class="anchor visible-anchor" href="#dxpropertygrid-customize-row-appearance">#</a>Customize Row Appearance
</h4>
<p> We added a <a href="https://docs.devexpress.com/WPF/DevExpress.Xpf.PropertyGrid.PropertyGridControl.RowStyle?v=24.1" target="_blank" rel="noopener">PropertyGridControl.RowStyle</a> property. Use this property to customize row
appearance/style settings. </p>
<p></p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-wpf-propertygrid-rowstyle.png" srcset="/subscriptions/i/24.1/24-1-wpf-propertygrid-rowstyle.png 1x, /subscriptions/i/24.1/24-1-wpf-propertygrid-rowstyle@2x.png 2x"
alt="Customize Row Appearance - WPF Property Grid, DevExpress" width="337" height="298" style="border: none" id="ctl00_ctl00_Content_Content_ctl2620"></div>
<p></p>
<p> As you would expect from a DevExpress WPF grid-based control, you have full control over row appearance. You can apply row styles based on a condition (use the WPF PropertyGrid's
<a href="https://docs.devexpress.com/WPF/DevExpress.Xpf.PropertyGrid.PropertyGridControl.RowStyleSelector?v=24.1" target="_blank" rel="noopener">RowStyleSelector</a> property or standard WPF trigger-based techniques), or you can use the
new <a href="https://docs.devexpress.com/WPF/DevExpress.Xpf.PropertyGrid.PropertyGridControl.AlternationCount?v=24.1" target="_blank" rel="noopener">AlternationCount</a> property to alternate row styles. </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">XAML</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="XML"><span class="hljs-tag"><<span class="hljs-name">dxprg:PropertyGridControl</span> <span class="hljs-attr">...</span>
<span class="hljs-attr">AlternationCount</span>=<span class="hljs-string">"3"</span>></span>
<span class="hljs-tag"><<span class="hljs-name">dxprg:PropertyGridControl.RowStyle</span>></span>
<span class="hljs-tag"><<span class="hljs-name">Style</span> <span class="hljs-attr">TargetType</span>=<span class="hljs-string">"dxprg:RowControl"</span>></span><span class="language-xml">
<span class="hljs-tag"><<span class="hljs-name">Style.Triggers</span>></span>
<span class="hljs-tag"><<span class="hljs-name">Trigger</span> <span class="hljs-attr">Property</span>=<span class="hljs-string">"ItemsControl.AlternationIndex"</span> <span class="hljs-attr">Value</span>=<span class="hljs-string">"1"</span>></span>
<span class="hljs-tag"><<span class="hljs-name">Setter</span> <span class="hljs-attr">Property</span>=<span class="hljs-string">"Background"</span> <span class="hljs-attr">Value</span>=<span class="hljs-string">"#122C2C2C"</span>/></span>
<span class="hljs-tag"></<span class="hljs-name">Trigger</span>></span>
<span class="hljs-tag"><<span class="hljs-name">Trigger</span> <span class="hljs-attr">Property</span>=<span class="hljs-string">"ItemsControl.AlternationIndex"</span> <span class="hljs-attr">Value</span>=<span class="hljs-string">"2"</span>></span>
<span class="hljs-tag"><<span class="hljs-name">Setter</span> <span class="hljs-attr">Property</span>=<span class="hljs-string">"Background"</span> <span class="hljs-attr">Value</span>=<span class="hljs-string">"LightGray"</span>/></span>
<span class="hljs-tag"></<span class="hljs-name">Trigger</span>></span>
<span class="hljs-tag"></<span class="hljs-name">Style.Triggers</span>></span>
</span><span class="hljs-tag"></<span class="hljs-name">Style</span>></span>
<span class="hljs-tag"></<span class="hljs-name">dxprg:PropertyGridControl.RowStyle</span>></span>
<span class="hljs-tag"></<span class="hljs-name">dxprg:PropertyGridControl</span>></span></code></pre>
</div>
</div> <span class="H-Separator"></span>
<h3 data-anchor="dxspreadsheet" data-toc-title="Spreadsheet">
<a name="dxspreadsheet" class="anchor"></a>Spreadsheet
</h3>
<h4 anchor="dxspreadsheet-accessibility">
<a name="dxspreadsheet-accessibility" class="anchor visible-anchor" href="#dxspreadsheet-accessibility">#</a>Accessibility Enhancements - Decorative Shapes
</h4>
<p> We added a <code data-renderer="hljs" class="csharp" data-control="Code-Inline">Decorative</code> property for the
<a href="https://docs.devexpress.com/OfficeFileAPI/DevExpress.Spreadsheet.Shape.Decorative?v=24.1" target="_blank" rel="noopener">Shape</a> class to mark document graphics (pictures, shapes and charts) as decorative. Decorative shapes
add visual interest, but they are not informative. Thus, you do not need to specify Alt Text (meaningful description) for decorative objects when you generate an accessible document. </p> <span class="H-Separator"></span>
<h4 anchor="xtraspreadsheet-text-align">
<a name="xtraspreadsheet-text-align" class="anchor visible-anchor" href="#xtraspreadsheet-text-align">#</a>Justify & Distributed Text Alignment
</h4>
<p> v24.1 adds support for <strong>Justify</strong> and <strong>Distributed</strong> horizontal alignment types within Spreadsheet cells. Excel files using these alignment options can be printed and exported to PDF. </p>
<p> You can use the <a href="https://docs.devexpress.com/OfficeFileAPI/DevExpress.Spreadsheet.Alignment.Horizontal" target="_blank" rel="noopener">Cell.Alignment.Horizontal</a> property to specify horizontal alignment in code. </p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-wpf-spreadsheet-justify-and-distributed-text-align.png"
srcset="/subscriptions/i/24.1/24-1-wpf-spreadsheet-justify-and-distributed-text-align.png 1x, /subscriptions/i/24.1/24-1-wpf-spreadsheet-justify-and-distributed-text-align@2x.png 2x"
alt="Justify and Distributed Text Alignment - WPF Spreadsheet, DevExpress" width="515" height="327" style="border: none" id="ctl00_ctl00_Content_Content_ctl2665"></div>
<p> The following code snippet specifies alignment in code: </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">C#</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="csharp"><span class="hljs-keyword">var</span> workbook = <span class="hljs-keyword">new</span> Workbook();
<span class="hljs-keyword">var</span> worksheet = workbook.Worksheets[<span class="hljs-number">0</span>];
Cell cellA1 = worksheet.Cells[<span class="hljs-string">"A1"</span>];
cellA1.Value = <span class="hljs-string">"Justified and top"</span>;
cellA1.Alignment.Horizontal = SpreadsheetHorizontalAlignment.Justify;
cellA1.Alignment.Vertical = SpreadsheetVerticalAlignment.Top;
workbook.ExportToPdf(<span class="hljs-string">"Result.pdf"</span>);</code></pre>
</div>
</div> <span class="H-Separator"></span>
<h4 anchor="dxspreadsheet-sort-filter-by-color">
<a name="dxspreadsheet-sort-filter-by-color" class="anchor visible-anchor" href="#dxspreadsheet-sort-filter-by-color">#</a>Sort and Filter by Color
</h4>
<p> The DevExpress WPF Spreadsheet ships with enhanced filter and sort-related capabilities. We added new APIs that can sort and filter workbook data by background and font color. Cell ranges filtered/sorted by cell color can also be
printed and exported to PDF. </p>
<p> Our Sorting APIs include new <a href="https://docs.devexpress.com/OfficeFileAPI/DevExpress.Spreadsheet.Worksheet.Sort.overloads?v=24.1" target="_blank" rel="noopener">Worksheet.Sort</a> method overloads designed to sort a specified
range by font color or fill setting (background color and pattern). </p>
<p> The following code snippet sorts cell values across two cell ranges - the first is sorted by a red font color and the second is sorted by fill settings specified for the first cell in the range: </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">C#</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="csharp">spreadsheetControl.LoadDocument(<span class="hljs-string">"sort-filter.xlsx"</span>);
Worksheet worksheet = spreadsheetControl.ActiveWorksheet;
<span class="hljs-comment">// Sort cell range by font color </span>
worksheet.Sort(worksheet[<span class="hljs-string">"B2:B10"</span>], Color.Red);
<span class="hljs-comment">// Sort cell range by fill color</span>
worksheet.Sort(worksheet[<span class="hljs-string">"D2:D10"</span>], worksheet[<span class="hljs-string">"D2"</span>].Fill);</code></pre>
</div>
</div>
<p> To filter cells by font or background color, you need to apply an auto-filter to the required cell range or table. Once complete, you need to obtain the required column from the <code data-renderer="hljs" class="csharp"
data-control="Code-Inline">AutoFilter.Columns</code> collection and call one of the following methods: </p>
<ul>
<li><a href="https://docs.devexpress.com/OfficeFileAPI/DevExpress.Spreadsheet.AutoFilterColumn.ApplyFillColorFilter(System.Drawing.Color)?v=24.1" target="_blank" rel="noopener">AutoFilterColumn.ApplyFillColorFilter(Color)</a></li>
<li><a href="https://docs.devexpress.com/OfficeFileAPI/DevExpress.Spreadsheet.AutoFilterColumn.ApplyFillFilter(DevExpress.Spreadsheet.Fill)?v=24.1" target="_blank" rel="noopener">AutoFilterColumn.ApplyFillFilter(Fill)</a></li>
<li><a href="https://docs.devexpress.com/OfficeFileAPI/DevExpress.Spreadsheet.AutoFilterColumn.ApplyFontColorFilter(System.Drawing.Color)?v=24.1" target="_blank" rel="noopener">AutoFilterColumn.ApplyFontColorFilter(Color)</a></li>
</ul>
<p> The following code snippet uses these methods for both cell range and table: </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">C#</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="csharp">spreadsheetControl.LoadDocument(<span class="hljs-string">"sort-filter.xlsx"</span>);
Worksheet worksheet = spreadsheetControl.ActiveWorksheet;
<span class="hljs-comment">// Apply an auto-filter to a cell range and filter the first column by font color</span>
worksheet.AutoFilter.Apply(worksheet[<span class="hljs-string">"B1:B10"</span>]);
worksheet.AutoFilter.Columns[<span class="hljs-number">0</span>].ApplyFontColorFilter(Color.Red);
<span class="hljs-comment">// Create a table, apply an auto-filter and filter the first column by fill color</span>
Table table = worksheet.Tables.Add(worksheet[<span class="hljs-string">"B12:B21"</span>], <span class="hljs-literal">true</span>);
table.AutoFilter.Apply();
table.AutoFilter.Columns[<span class="hljs-number">0</span>].ApplyFillColorFilter(Color.Red);</code></pre>
</div>
</div>
<p> In addition, our new APIs allow you to sort data across a filtered range (when auto-filter is enabled) and sort cells by their values/colors simultaneously (using sorting conditions). </p>
<p><a href="https://docs.devexpress.com/WPF/17471/controls-and-libraries/spreadsheet/data-presentation/sorting#sort-range-by-color" target="_blank" rel="noopener">Documentation: Sort Cell Range by Color</a></p> <span
class="H-Separator"></span>
<h4 anchor="dxspreadsheet-export-cell-range-to-svg">
<a name="dxspreadsheet-export-cell-range-to-svg" class="anchor visible-anchor" href="#dxspreadsheet-export-cell-range-to-svg">#</a>Export Cell Range to SVG
</h4>
<p> In this release, we enhanced our <a href="https://docs.devexpress.com/OfficeFileAPI/DevExpress.Spreadsheet.CellRangeExtensions.ExportToImage.overloads?v=24.1" target="_blank" rel="noopener">CellRangeExtensions.ExportToImage</a> method
and added support for the SVG image format. </p>
<div class="Attention">
<p class="sys-h-align-left"> The <code data-renderer="hljs" class="csharp" data-control="Code-Inline">CellRangeExtensions</code> class is defined in the DevExpress.Docs.v24.1.dll assembly. Add this assembly to your project or install
the DevExpress.Document.Processor NuGet Package to use <code data-renderer="hljs" class="csharp" data-control="Code-Inline">CellRangeExtensions</code> members. To use this class in production code, you will need an active
<a href="/products/net/office-file-api/#Pricing">DevExpress Office File API</a> or <a href="/buy">DevExpress Universal Subscription</a>. </p>
</div>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">C#</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="csharp">spreadsheetControl.LoadDocument(<span class="hljs-string">"InvestmentPortfolio.xlsx"</span>, DocumentFormat.Xlsx);
Worksheet worksheet = spreadsheetControl.ActiveWorksheet;
worksheet.Range[<span class="hljs-string">"B18:I30"</span>].ExportToImage(<span class="hljs-string">"cell_range_image.svg"</span>, ImageFileFormat.Svg);</code></pre>
</div>
</div>
<p> SVG Export is also available from the user interface - open the Print Preview dialog, click the Export to Image button, choose the SVG format in the Image Options dialog and complete document export. </p> <span
class="H-Separator"></span>
<h3 data-anchor="dxthemes" data-toc-title="Lightweight Themes">
<a name="dxthemes" class="anchor"></a>Lightweight Themes
</h3>
<h4 anchor="dxthemes-obtain-palette-color">
<a name="dxthemes-obtain-palette-color" class="anchor visible-anchor" href="#dxthemes-obtain-palette-color">#</a>Obtain Lightweight Theme Palette Color
</h4>
<p> With v24.1, you can effortlessly access color information from existing palettes that ship as part of our Lightweight themes. This functionality extends to custom color palettes, allowing you to use colors that reflect the unique
identity of your WPF application. </p>
<p><a href="https://docs.devexpress.com/WPF/404442/common-concepts/themes/lightweight-themes?v=24.1#obtain-palette-colors" target="_blank" rel="noopener">Documentation</a></p> <span class="H-Separator"></span>
<h3 data-anchor="wpf-survey" data-toc-title="Survey - WPF">
<a name="wpf-survey" class="anchor"></a>Survey - WPF
</h3>
<h4 anchor=""> Your Feedback Matters! </h4>
<div id="ctl00_ctl00_Content_Content_SurveyContainer" data-control="survey" class="InlineSurvey">
<div data-role="SurveyContent" data-markdown="false" data-partial="false" data-multiple-results="None" data-survey-id="24e59506-3ec3-40ce-bd4c-d39fcc785975" data-auth-required="true"
data-user-data="{"IsLoggedIn":false,"IsEmployee":false,"CustomerId":null}" style="display: none;">
</div>
<div data-role="AuthRequired" style="display: block;"> Please <a href="https://www.devexpress.com/MyAccount/LogIn/?returnUrl=https%3a%2f%2fwww.devexpress.com%2fsubscriptions%2fwhats-new%2f">login</a> to complete the survey. </div>
<div data-role="Loading" style="display: none;">
<img src="../../Content/Editors/ajax-loader.gif" style="border-width:0px;">
</div>
<div data-role="Completed" style="display: none;">
<h3> Survey Completed </h3>
<p class="sys-max-width-md-80 sys-max-width-lg-60">Thank you for taking the time to complete this survey. Your responses have now been posted. If you want to follow up with additional information, feel free to send us an email at
<a href="mailto:clientservices@devexpress.com">clientservices@devexpress.com</a> anytime. </p>
</div>
<div data-role="AlreadyPassed" style="display: none;">
<h3> You've Already Completed This Survey </h3>
<p class="sys-max-width-md-80 sys-max-width-lg-60">Our records show that you have already completed this survey. If you want to follow up with additional information, send us an email at
<a href="mailto:clientservices@devexpress.com">clientservices@devexpress.com</a>.</p>
</div>
<div data-role="Expired" style="display: none;">
<h3> This survey has expired </h3>
<p>If you want to share your feedback or request new functionality, please submit a new support ticket via the <a href="https://supportcenter.devexpress.com/">DevExpress Support Center</a>. We’ll be happy to follow up.</p>
</div>
</div>
<h2 class="SectionHeader" data-anchor="devextreme" data-toc-title="JavaScript & ASP.NET Core">
<a data-whatsnew-platform="devextreme" name="devextreme" class="anchor"></a>JavaScript & ASP.NET Core Components v24.1
</h2>
<div class="WhatsNewTOC grid sys-visibility-hidden sys-visibility-hidden sys-visibility-sm-shown">
<div class="row">
<div class="col-sm-6 col-md-3 col-order-1">
<p><a href="#js-splitter"><span>New Splitter Component</span></a></p>
<p><a href="#js-ui-ux-api"><span>UI/UX and API Enhancements</span></a></p>
<p><a href="#js-bundle"><span>JS Script Size</span></a></p>
</div>
<div class="col-sm-6 col-md-3 col-sm-order-3 col-md-order-2">
<p><a href="#js-angular-18"><span>Angular 18 Support</span></a></p>
<p><a href="#js-angular-httpmodule"><span>New DxHttpModule for Angular</span></a></p>
<p><a href="#js-shadow-dom"><span>Shadow DOM Support (CTP)</span></a></p>
</div>
<div class="column-break sm">
</div>
<div class="col-sm-6 col-md-3 col-sm-order-2 col-md-order-3">
<p><a href="#js-accessibility"><span>Accessibility</span></a></p>
<p><a href="#aspnetcore-date-only-time-only"><span>ASP.NET Core - DateOnly/TimeOnly Type Support</span></a></p>
<p><a href="#aspnetcore-data-validation"><span>ASP.NET Core - Data Validation</span></a></p>
</div>
<div class="col-sm-6 col-md-3 col-order-4">
<p><a href="#aspnetcore-richtexteditor"><span>ASP.NET Core - Rich Text Editor</span></a></p>
<p><a href="#devextreme-survey"><span>Survey - JavaScript & ASP.NET Core</span></a></p>
</div>
</div>
</div>
<div class="Attention">
<p><strong>Your feedback matters.</strong><br> Please, review the description of <strong>JavaScript</strong> and <strong>ASP.NET Core</strong> related features below and leave your feedback at the end of the section. </p>
<p><a href="#devextreme-survey">Go to the survey now.</a></p>
</div>
<h3 data-anchor="js-splitter" data-toc-title="New Splitter Component">
<a name="js-splitter" class="anchor"></a>New Splitter Component
</h3>
<p> Our new <a href="https://js.devexpress.com/Documentation/24_1/ApiReference/UI_Components/dxSplitter/" target="_blank" rel="noopener">Splitter</a> component allows you to divide a page or section into multiple adjustable panes. </p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-js-splitter.png" srcset="/subscriptions/i/24.1/24-1-js-splitter.png 1x, /subscriptions/i/24.1/24-1-js-splitter@2x.png 2x" alt="Splitter Component - DevExtreme, DevExpress"
width="800" height="400" style="border: none" id="ctl00_ctl00_Content_Content_ctl3163"></div>
<p> These panes can be: </p>
<ul>
<li><a href="https://js.devexpress.com/Documentation/24_1/ApiReference/UI_Components/dxSplitter/Configuration/items/#resizable" target="_blank" rel="noopener">resizable</a> - A handle with a drag icon allows users to modify size. </li>
<li><a href="https://js.devexpress.com/Documentation/24_1/ApiReference/UI_Components/dxSplitter/Configuration/items/#collapsible" target="_blank" rel="noopener">collapsible</a> - A handle with an arrow icon allows users to collapse the
pane. </li>
</ul>
<p> If you enable both these properties, the handle displays both icons and users can both resize/collapse a given pane as desired. If both properties are false, the handle remains hidden. </p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-js-nested-panes.gif" srcset="/subscriptions/i/24.1/24-1-js-nested-panes.gif 1x, /subscriptions/i/24.1/24-1-js-nested-panes@2x.gif 2x"
alt="Splitter: Resizable and Collapsible Panes - DevExtreme, DevExpress" width="720" height="200" style="border: none" id="ctl00_ctl00_Content_Content_ctl3169"></div>
<p> The Splitter component can be oriented either vertically or horizontally. Orientation affects the following pane-related properties (can be specified in pixels or percents) </p>
<ul>
<li><a href="https://js.devexpress.com/Documentation/24_1/ApiReference/UI_Components/dxSplitter/Configuration/items/#size" target="_blank" rel="noopener">size</a> - Specifies initial width (horizontal orientation) or height (vertical)
of the pane. </li>
<li><a href="https://js.devexpress.com/Documentation/24_1/ApiReference/UI_Components/dxSplitter/Configuration/items/#maxSize" target="_blank" rel="noopener">maxSize</a>,
<a href="https://js.devexpress.com/Documentation/24_1/ApiReference/UI_Components/dxSplitter/Configuration/items/#minSize" target="_blank" rel="noopener">minSize</a> - Defines resizing limits for the pane. </li>
<li><a href="https://js.devexpress.com/Documentation/24_1/ApiReference/UI_Components/dxSplitter/Configuration/items/#collapsedSize" target="_blank" rel="noopener">collapsedSize</a> - Specifies the size of a collapsible pane when
collapsed. </li>
</ul>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">Angular</li>
<li>React</li>
<li>Vue</li>
<li>jQuery</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="javascript"><dx-splitter orientation=<span class="hljs-string">"vertical"</span>>
<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">dxi-item</span>
[<span class="hljs-attr">collapsible</span>]=<span class="hljs-string">"true"</span>
<span class="hljs-attr">size</span>=<span class="hljs-string">"50%"</span>
<span class="hljs-attr">minSize</span>=<span class="hljs-string">"20px"</span>
<span class="hljs-attr">сollapsedSize</span>=<span class="hljs-string">"30px"</span>
></span>
<span class="hljs-tag"></<span class="hljs-name">dxi-item</span>></span></span>
</dx-splitter></code></pre>
</div>
<div class="CodeContainer">
<pre><code data-renderer="hljs" class="javascript"><span class="hljs-keyword">const</span> <span class="hljs-title function_">App</span> = (<span class="hljs-params"></span>) => (
<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">Splitter</span> <span class="hljs-attr">orientation</span>=<span class="hljs-string">"vertical"</span>></span>
<span class="hljs-tag"><<span class="hljs-name">Item</span>
<span class="hljs-attr">collapsible</span>=<span class="hljs-string">{true}</span>
<span class="hljs-attr">size</span>=<span class="hljs-string">"50%"</span>
<span class="hljs-attr">minSize</span>=<span class="hljs-string">"20px"</span>
<span class="hljs-attr">сollapsedSize</span>=<span class="hljs-string">"30px"</span>
/></span>
<span class="hljs-tag"></<span class="hljs-name">Splitter</span>></span></span>
);
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-title class_">App</span>;</code></pre>
</div>
<div class="CodeContainer">
<pre><code data-renderer="hljs" class="javascript"><template>
<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">DxSplitter</span> <span class="hljs-attr">orientation</span>=<span class="hljs-string">"vertical"</span>></span>
<span class="hljs-tag"><<span class="hljs-name">DxItem</span>
<span class="hljs-attr">:collapsible</span>=<span class="hljs-string">"true"</span>
<span class="hljs-attr">size</span>=<span class="hljs-string">"50%"</span>
<span class="hljs-attr">min-size</span>=<span class="hljs-string">"20px"</span>
<span class="hljs-attr">collapsed-size</span>=<span class="hljs-string">"30px"</span>
/></span>
<span class="hljs-tag"></<span class="hljs-name">DxSplitter</span>></span></span>
</template></code></pre>
</div>
<div class="CodeContainer">
<pre><code data-renderer="hljs" class="javascript">$(<span class="hljs-string">'#splitter'</span>).<span class="hljs-title function_">dxSplitter</span>({
<span class="hljs-attr">orientation</span>: <span class="hljs-string">'vertical'</span>,
<span class="hljs-attr">items</span>: [
{
<span class="hljs-attr">collapsible</span>: <span class="hljs-literal">true</span>,
<span class="hljs-attr">size</span>: <span class="hljs-string">'50%'</span>,
<span class="hljs-attr">minSize</span>: <span class="hljs-string">'20px'</span>,
<span class="hljs-attr">collapsedSize</span>: <span class="hljs-string">'30px'</span>,
},
],
});</code></pre>
</div>
</div>
<p> Splitter panes can contain multiple content types, ranging from simple HTML to complex components. You can place HTML markup inside the item tag or use the following properties to populate panes with content: </p>
<ul>
<li><a href="https://js.devexpress.com/Documentation/24_1/ApiReference/UI_Components/dxSplitter/Configuration/#itemTemplate" target="_blank" rel="noopener">itemTemplate</a> - Defines a custom template for all panes. </li>
<li><a href="https://js.devexpress.com/Documentation/24_1/ApiReference/UI_Components/dxSplitter/Configuration/items/#template" target="_blank" rel="noopener">template</a> - Sets a custom template for each specific pane. </li>
</ul>
<p> To customize Splitter appearance, specify the <a href="https://js.devexpress.com/Documentation/24_1/ApiReference/UI_Components/dxSplitter/Configuration/#separatorSize" target="_blank" rel="noopener">separatorSize</a> property to
modify the size of the handle's shorter side. You can also alter color and icons through CSS. </p>
<p> Enable <a href="https://js.devexpress.com/Documentation/24_1/ApiReference/UI_Components/dxSplitter/Configuration/#allowKeyboardNavigation" target="_blank" rel="noopener">allowKeyboardNavigation</a> in the Splitter component to control
Splitter actions through shortcut keys, mirroring mouse functions. To see the full list of shortcuts, refer to the following help topic:
<a href="https://js.devexpress.com/Documentation/24_1/Guide/UI_Components/Splitter/Accessibility/" target="_blank" rel="noopener">Accessibility</a>. </p>
<p> For complex layouts, <a href="https://js.devexpress.com/Documentation/24_1/ApiReference/UI_Components/dxSplitter/Configuration/items/#splitter" target="_blank" rel="noopener">nest Splitters</a> as illustrated in our demo (which also
highlights use of templates for content insertion). </p>
<p> Select one of the following supported dev frameworks to explore the capabilities of this new feature: </p>
<p><a href="https://js.devexpress.com/Angular/Demos/WidgetsGallery/Demo/Splitter/Overview/" target="_blank" rel="noopener">Angular</a> |
<a href="https://js.devexpress.com/React/Demos/WidgetsGallery/Demo/Splitter/Overview/" target="_blank" rel="noopener">React</a> |
<a href="https://js.devexpress.com/Vue/Demos/WidgetsGallery/Demo/Splitter/Overview/" target="_blank" rel="noopener">Vue</a> |
<a href="https://js.devexpress.com/jQuery/Demos/WidgetsGallery/Demo/Splitter/Overview/" target="_blank" rel="noopener">jQuery</a> |
<a href="https://demos.devexpress.com/aspnetcore/Demo/Splitter/Overview/" target="_blank" rel="noopener">ASP.NET Core</a> |
<a href="https://demos.devexpress.com/ASPNetMvc/Demo/Splitter/Overview/" target="_blank" rel="noopener">ASP.NET MVC</a></p> <span class="H-Separator"></span>
<h3 data-anchor="js-ui-ux-api" data-toc-title="UI/UX and API Enhancements">
<a name="js-ui-ux-api" class="anchor"></a>UI/UX and API Enhancements
</h3>
<h4 anchor="js-dropdownbutton">
<a name="js-dropdownbutton" class="anchor visible-anchor" href="#js-dropdownbutton">#</a>DropDownButton - Custom Button Template
</h4>
<p> With v24.1, you can replace the base button in <code data-renderer="hljs" class="csharp" data-control="Code-Inline">DropDownButton</code> with
<a href="https://js.devexpress.com/Documentation/24_1/ApiReference/UI_Components/dxDropDownButton/Configuration/#template" target="_blank" rel="noopener">custom content</a> (such as an avatar or multiline text). </p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-js-dropdown.png" srcset="/subscriptions/i/24.1/24-1-js-dropdown.png 1x, /subscriptions/i/24.1/24-1-js-dropdown@2x.png 2x"
alt="DropDownButton with Custom Content - DevExtreme, DevExpress" width="560" height="120" style="border: none" id="ctl00_ctl00_Content_Content_ctl3231"></div>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">Angular</li>
<li>React</li>
<li>Vue</li>
<li>jQuery</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="javascript"><dx-drop-down-button icon=<span class="hljs-string">"spindown"</span> template=<span class="hljs-string">"button-template"</span>>
<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">div</span> *<span class="hljs-attr">dxTemplate</span>=<span class="hljs-string">"let data of 'button-template'"</span>></span>
<span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-container"</span>></span>
<span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"name"</span>></span> {{ currentEmployee.FirstName }} {{ currentEmployee.LastName }} <span class="hljs-tag"></<span class="hljs-name">div</span>></span>
<span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"position"</span>></span> {{ currentEmployee.Position }} <span class="hljs-tag"></<span class="hljs-name">div</span>></span>
<span class="hljs-tag"></<span class="hljs-name">div</span>></span>
<span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"dx-icon-{{ data.icon }} dx-icon"</span>></span><span class="hljs-tag"></<span class="hljs-name">span</span>></span>
<span class="hljs-tag"></<span class="hljs-name">div</span>></span></span>
</dx-drop-down-button></code></pre>
</div>
<div class="CodeContainer">
<pre><code data-renderer="hljs" class="javascript"><span class="hljs-keyword">const</span> <span class="hljs-title function_">renderButton</span> = (<span class="hljs-params">data</span>) => {
<span class="hljs-keyword">return</span> (
<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">React.Fragment</span>></span>
<span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-container"</span>></span>
<span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"name"</span>></span> {currentEmployee.FirstName} {currentEmployee.LastName} <span class="hljs-tag"></<span class="hljs-name">div</span>></span>
<span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"position"</span>></span> {currentEmployee.Position} <span class="hljs-tag"></<span class="hljs-name">div</span>></span>
<span class="hljs-tag"></<span class="hljs-name">div</span>></span>
<span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>"<span class="hljs-attr">dx-icon-</span>" + <span class="hljs-attr">data.icon</span> + " <span class="hljs-attr">dx-icon</span>"}></span><span class="hljs-tag"></<span class="hljs-name">span</span>></span>
<span class="hljs-tag"></<span class="hljs-name">React.Fragment</span>></span></span>
);
};
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-keyword">function</span> <span class="hljs-title function_">App</span>(<span class="hljs-params"></span>) {
<span class="hljs-keyword">return</span> (
<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">DropDownButton</span>
<span class="hljs-attr">icon</span>=<span class="hljs-string">"spindown"</span>
<span class="hljs-attr">render</span>=<span class="hljs-string">{renderButton}</span>
/></span></span>
);
}</code></pre>
</div>
<div class="CodeContainer">
<pre><code data-renderer="hljs" class="javascript"><template>
<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">DxDropDownButton</span>
<span class="hljs-attr">icon</span>=<span class="hljs-string">"spindown"</span>
<span class="hljs-attr">template</span>=<span class="hljs-string">"button-template"</span>
></span>
<span class="hljs-tag"><<span class="hljs-name">template</span> #<span class="hljs-attr">button-template</span>=<span class="hljs-string">"{ data }"</span>></span>
<span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-container"</span>></span>
<span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"name"</span>></span> {{ currentEmployee.FirstName }} {{ currentEmployee.LastName }} <span class="hljs-tag"></<span class="hljs-name">div</span>></span>
<span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"position"</span>></span> {{ currentEmployee.Position }} <span class="hljs-tag"></<span class="hljs-name">div</span>></span>
<span class="hljs-tag"></<span class="hljs-name">div</span>></span>
<span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">:class</span>=<span class="hljs-string">"'dx-icon-' + data.icon + ' dx-icon'"</span>></span><span class="hljs-tag"></<span class="hljs-name">span</span>></span>
<span class="hljs-tag"></<span class="hljs-name">template</span>></span>
<span class="hljs-tag"></<span class="hljs-name">DxDropDownButton</span>></span></span>
</template></code></pre>
</div>
<div class="CodeContainer">
<pre><code data-renderer="hljs" class="javascript">$(<span class="hljs-string">"#myDropDownButton"</span>).<span class="hljs-title function_">dxDropDownButton</span>({
<span class="hljs-attr">icon</span>: <span class="hljs-string">'spindown'</span>,
<span class="hljs-attr">template</span>: <span class="hljs-function">(<span class="hljs-params">data, $element</span>) =></span> {
<span class="hljs-keyword">const</span> $textContainer = $(<span class="hljs-string">'<div class="text-container">'</span>).<span class="hljs-title function_">appendTo</span>($element);
$(<span class="hljs-string">`<div class='name'><span class="hljs-subst">${currentEmployee.FirstName}</span> {currentEmployee.LastName}</div>`</span>).<span class="hljs-title function_">appendTo</span>($textContainer);
$(<span class="hljs-string">`<div class='position'> <span class="hljs-subst">${currentEmployee.Position}</span> </div>`</span>).<span class="hljs-title function_">appendTo</span>($textContainer);
$(<span class="hljs-string">`<span class="dx-icon-<span class="hljs-subst">${data.icon}</span> dx-icon"></span>`</span>).<span class="hljs-title function_">appendTo</span>($element);
},
});</code></pre>
</div>
</div>
<p> Select one of the following supported dev frameworks to explore the capabilities of this new feature: </p>
<p><a href="https://js.devexpress.com/Angular/Demos/WidgetsGallery/Demo/DropDownButton/Overview/" target="_blank" rel="noopener">Angular</a> |
<a href="https://js.devexpress.com/React/Demos/WidgetsGallery/Demo/DropDownButton/Overview/" target="_blank" rel="noopener">React</a> |
<a href="https://js.devexpress.com/Vue/Demos/WidgetsGallery/Demo/DropDownButton/Overview/" target="_blank" rel="noopener">Vue</a> |
<a href="https://js.devexpress.com/jQuery/Demos/WidgetsGallery/Demo/DropDownButton/Overview/" target="_blank" rel="noopener">jQuery</a> |
<a href="https://demos.devexpress.com/aspnetcore/Demo/DropDownButton/Overview/" target="_blank" rel="noopener">ASP.NET Core</a> |
<a href="https://demos.devexpress.com/ASPNetMvc/Demo/DropDownButton/Overview/" target="_blank" rel="noopener">ASP.NET MVC</a></p> <span class="H-Separator"></span>
<h4 anchor="js-menu">
<a name="js-menu" class="anchor visible-anchor" href="#js-menu">#</a>Menu/ContextMenu — Item Scrolling
</h4>
<p> Submenus that exceed page size (in <a href="https://js.devexpress.com/Documentation/24_1/ApiReference/UI_Components/dxMenu/" target="_blank" rel="noopener">Menu</a> or
<a href="https://js.devexpress.com/Documentation/24_1/ApiReference/UI_Components/dxContextMenu/" target="_blank" rel="noopener">ContextMenu</a>) can now be scrolled. </p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-js-menu-item-scrolling.png" srcset="/subscriptions/i/24.1/24-1-js-menu-item-scrolling.png 1x, /subscriptions/i/24.1/24-1-js-menu-item-scrolling@2x.png 2x"
alt="Item Scrolling in Menu and ContextMenu - DevExtreme, DevExpress" width="500" height="270" style="border: none" id="ctl00_ctl00_Content_Content_ctl3267"></div>
<p> You can use CSS stylesheets to customize submenus as needs dictate. For instance, the following code snippet restricts submenu height in <code data-renderer="hljs" class="csharp" data-control="Code-Inline">ContextMenu</code>: </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">CSS</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="css"><span class="hljs-selector-class">.dx-context-menu</span> <span class="hljs-selector-class">.dx-menu-items-container</span> {
<span class="hljs-attribute">max-height</span>: <span class="hljs-number">200px</span>;
}</code></pre>
</div>
</div>
<p> In the <code data-renderer="hljs" class="csharp" data-control="Code-Inline">Menu</code> component, use the
<a href="https://js.devexpress.com/Documentation/24_1/ApiReference/UI_Components/dxMenu/Configuration/#onSubmenuShowing" target="_blank" rel="noopener">onSubmenuShowing</a> function to configure scroll-related settings. For instance,
you can restrict the size of the submenu when item count surpasses a specified limit: </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">Angular</li>
<li>React</li>
<li>Vue</li>
<li>jQuery</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="javascript"><span class="hljs-title function_">onSubmenuShowing</span>({ submenuContainer, itemData } {
<span class="hljs-keyword">if</span> (itemData.<span class="hljs-property">items</span>.<span class="hljs-property">length</span> > <span class="hljs-number">5</span>) {
submenuContainer.<span class="hljs-property">style</span>.<span class="hljs-property">maxHeight</span> = <span class="hljs-variable language_">this</span>.<span class="hljs-property">limitSubmenuHeight</span> ? <span class="hljs-string">`200px`</span> : <span class="hljs-string">''</span>;
}
}</code></pre>
</div>
<div class="CodeContainer">
<pre><code data-renderer="hljs" class="javascript"><span class="hljs-keyword">const</span> onSubmenuShowing = <span class="hljs-title function_">useCallback</span>(<span class="hljs-function">(<span class="hljs-params">{ submenuContainer, itemData }</span>) =></span> {
<span class="hljs-keyword">if</span> (itemData.<span class="hljs-property">items</span>.<span class="hljs-property">length</span> > <span class="hljs-number">5</span>) {
submenuContainer.<span class="hljs-property">style</span>.<span class="hljs-property">maxHeight</span> = limitSubmenuHeight ? <span class="hljs-string">`200px`</span> : <span class="hljs-string">''</span>;
}
}, []);</code></pre>
</div>
<div class="CodeContainer">
<pre><code data-renderer="hljs" class="javascript"><span class="hljs-keyword">function</span> <span class="hljs-title function_">onSubmenuShowing</span>(<span class="hljs-params">{ submenuContainer, itemData } {
<span class="hljs-keyword">if</span> (itemData.items.length > <span class="hljs-number">5</span>) {
submenuContainer.style.maxHeight = limitSubmenuHeight.value ? <span class="hljs-string">'200px'</span> : <span class="hljs-string">''</span>;
}
}</span></code></pre>
</div>
<div class="CodeContainer">
<pre><code data-renderer="hljs" class="javascript"><span class="hljs-attr">onSubmenuShowing</span>: <span class="hljs-function">(<span class="hljs-params">{ submenuContainer, itemData }</span>) =></span> {
<span class="hljs-keyword">if</span> (itemData.<span class="hljs-property">items</span>.<span class="hljs-property">length</span> > <span class="hljs-number">5</span>) {
$(submenuContainer).<span class="hljs-title function_">css</span>(<span class="hljs-string">'maxHeight'</span>, <span class="hljs-number">200</span> || <span class="hljs-string">''</span>);
}
}</code></pre>
</div>
</div>
<p> Select one of the following supported dev frameworks to explore the capabilities of this new feature: </p>
<p> Menu: <a href="https://js.devexpress.com/Angular/Demos/WidgetsGallery/Demo/Menu/Scrolling/" target="_blank" rel="noopener">Angular</a> |
<a href="https://js.devexpress.com/React/Demos/WidgetsGallery/Demo/Menu/Scrolling/" target="_blank" rel="noopener">React</a> |
<a href="https://js.devexpress.com/Vue/Demos/WidgetsGallery/Demo/Menu/Scrolling/" target="_blank" rel="noopener">Vue</a> |
<a href="https://js.devexpress.com/jQuery/Demos/WidgetsGallery/Demo/Menu/Scrolling/" target="_blank" rel="noopener">jQuery</a> |
<a href="https://demos.devexpress.com/aspnetcore/Demo/Menu/Scrolling/" target="_blank" rel="noopener">ASP.NET Core</a> |
<a href="https://demos.devexpress.com/ASPNetMvc/Demo/Menu/Scrolling/" target="_blank" rel="noopener">ASP.NET MVC</a></p>
<p> ContextMenu: <a href="https://js.devexpress.com/Angular/Demos/WidgetsGallery/Demo/ContextMenu/Scrolling/" target="_blank" rel="noopener">Angular</a> |
<a href="https://js.devexpress.com/React/Demos/WidgetsGallery/Demo/ContextMenu/Scrolling/" target="_blank" rel="noopener">React</a> |
<a href="https://js.devexpress.com/Vue/Demos/WidgetsGallery/Demo/ContextMenu/Scrolling/" target="_blank" rel="noopener">Vue</a> |
<a href="https://js.devexpress.com/jQuery/Demos/WidgetsGallery/Demo/ContextMenu/Scrolling/" target="_blank" rel="noopener">jQuery</a> |
<a href="https://demos.devexpress.com/aspnetcore/Demo/ContextMenu/Scrolling/" target="_blank" rel="noopener">ASP.NET Core</a> |
<a href="https://demos.devexpress.com/ASPNetMvc/Demo/ContextMenu/Scrolling/" target="_blank" rel="noopener">ASP.NET MVC</a></p> <span class="H-Separator"></span>
<h4 anchor="js-form">
<a name="js-form" class="anchor visible-anchor" href="#js-form">#</a>Form — Group Caption Custom Content
</h4>
<p> Our new Form <a href="https://js.devexpress.com/Documentation/24_1/ApiReference/UI_Components/dxForm/Item_Types/GroupItem/#captionTemplate" target="_blank" rel="noopener">groupItem.captionTemplate</a> option enables custom content
replacement for group captions. </p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-js-form-group-caption-custom-content.png"
srcset="/subscriptions/i/24.1/24-1-js-form-group-caption-custom-content.png 1x, /subscriptions/i/24.1/24-1-js-form-group-caption-custom-content@2x.png 2x" alt="Group Caption Custom Content - DevExtreme Form, DevExpress" width="700"
height="540" style="border: none" id="ctl00_ctl00_Content_Content_ctl3332"></div>
<p> Select one of the following supported dev frameworks to explore the capabilities of this new feature: </p>
<p><a href="https://js.devexpress.com/Angular/Demos/WidgetsGallery/Demo/Form/GroupedFields/" target="_blank" rel="noopener">Angular</a> |
<a href="https://js.devexpress.com/React/Demos/WidgetsGallery/Demo/Form/GroupedFields/" target="_blank" rel="noopener">React</a> |
<a href="https://js.devexpress.com/Vue/Demos/WidgetsGallery/Demo/Form/GroupedFields/" target="_blank" rel="noopener">Vue</a> |
<a href="https://js.devexpress.com/jQuery/Demos/WidgetsGallery/Demo/Form/GroupedFields/" target="_blank" rel="noopener">jQuery</a> |
<a href="https://demos.devexpress.com/aspnetcore/Demo/Form/GroupedFields/" target="_blank" rel="noopener">ASP.NET Core</a> |
<a href="https://demos.devexpress.com/ASPNetMvc/Demo/Form/GroupedFields/" target="_blank" rel="noopener">ASP.NET MVC</a></p> <span class="H-Separator"></span>
<h4 anchor="js-html-editor">
<a name="js-html-editor" class="anchor visible-anchor" href="#js-html-editor">#</a>HTML Editor — Spellcheck and CSP Support
</h4>
<p> The <a href="https://js.devexpress.com/Documentation/24_1/ApiReference/UI_Components/dxHtmlEditor/" target="_blank" rel="noopener">DevExtreme HTML Editor</a> now uses spellcheck functionality across all supported browsers. As you
would expect, this addition enhances text editing capabilities through real-time spelling correction/suggestion support. </p>
<p> Previous versions required <a href="https://js.devexpress.com/Documentation/24_1/Guide/Common/Security_Considerations/#Content_Security_Policy" target="_blank" rel="noopener">Content Security Policy (CSP)</a> directives when passing
markup with inline styles to our HTML Editor. The DevExtreme HTML Editor v24.1 fully supports CSP. </p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-js-htmleditor-spellcheck-csp.png" srcset="/subscriptions/i/24.1/24-1-js-htmleditor-spellcheck-csp.png 1x, /subscriptions/i/24.1/24-1-js-htmleditor-spellcheck-csp@2x.png 2x"
alt="Spellcheck and CSP Support - DevExtreme HTML Editor, DevExpress" width="820" height="721" style="border: none" id="ctl00_ctl00_Content_Content_ctl3369"></div> <span class="H-Separator"></span>
<h3 data-anchor="js-bundle" data-toc-title="JS Script Size">
<a name="js-bundle" class="anchor"></a>JS Script Size
</h3>
<p> In our last major release cycle (v23.2), we reduced <a href="https://www.devexpress.com/subscriptions/new-2023-2.xml#js-reduce-css-size" target="_blank" rel="noopener">CSS size</a> for built-in themes. In this release cycle, we
reduced DevExtreme JS scripts size as follows: </p>
<ul>
<li>We updated the ECMAScript compilation target for DevExtreme JS code. This eliminated the need for complicated syntactic constructions (due to transpiling) for operations supported by
<a href="https://js.devexpress.com/Documentation/Guide/Common/Supported_Browsers/" target="_blank" rel="noopener">all modern browsers</a>.</li>
<li>We ceased storage of time zone data. We switched to an internal browser time zone engine for time zone related operations.</li>
</ul>
<p> These modifications reduced bundle size by approximately 12%. </p><img src="/subscriptions/i/24.1/24-1-js-bundle-size.png" srcset="/subscriptions/i/24.1/24-1-js-bundle-size.png 1x, /subscriptions/i/24.1/24-1-js-bundle-size@2x.png 2x"
alt="DevExtreme JS Bundle Size, DevExpress" width="1080" height="480" style="border: none" id="ctl00_ctl00_Content_Content_ctl3383"> <span class="H-Separator"></span>
<h3 data-anchor="js-angular-18" data-toc-title="Angular 18 Support">
<a name="js-angular-18" class="anchor"></a>Angular 18 Support
</h3>
<p> DevExtreme v24.1 supports Angular 18. Earlier versions (such as DevExtreme v23.2) are not compatible with Angular 18. </p>
<p> Refer to the Angular <a href="https://angular.dev/update-guide" target="_blank" rel="noopener">Update Guide</a> and our
<a href="https://js.devexpress.com/Documentation/Guide/Common/Migrate_to_the_New_Version/" target="_blank" rel="noopener">Migrate to the New Version</a> help topic to update your application. </p> <span class="H-Separator"></span>
<h3 data-anchor="js-angular-httpmodule" data-toc-title="New DxHttpModule for Angular">
<a name="js-angular-httpmodule" class="anchor"></a>New DxHttpModule for Angular
</h3>
<h4 anchor="js-simplified-request-interception">
<a name="js-simplified-request-interception" class="anchor visible-anchor" href="#js-simplified-request-interception">#</a>Simplified Request Interception
</h4>
<p> Angular <a href="https://angular.io/api/common/http/HttpClientModule" target="_blank" rel="noopener">HttpClientModule</a> is a module that simplifies HTTP requests. It supports request and response interceptors, which allows you to
introduce capabilities such as authentication tokens or logging across all HTTP requests. </p>
<p> Previously, our <a href="https://js.devexpress.com/Documentation/24_1/ApiReference/Data_Layer/DataSource/" target="_blank" rel="noopener">DataSource</a>,
<a href="https://js.devexpress.com/Documentation/24_1/ApiReference/UI_Components/dxFileUploader/" target="_blank" rel="noopener">FileUploader</a>, and
<a href="https://js.devexpress.com/Documentation/24_1/ApiReference/UI_Components/dxMap/" target="_blank" rel="noopener">Map</a> components depended on non-native Angular Ajax requests for server communication. </p>
<p> With v24.1, we transitioned these components from Ajax to the <code data-renderer="hljs" class="csharp" data-control="Code-Inline">HttpClientModule</code>. Simply import our <code data-renderer="hljs" class="csharp"
data-control="Code-Inline">DxHttpModule</code> to activate this new functionality. </p>
<p> In the following example, DataSource utilizes DxHttpModule for request interception. </p>
<p><a href="https://codesandbox.io/p/devbox/devextreme-24-1-httpclientmodule-support-vllnw8?file=%2Fsrc%2Fapp%2Finterceptors.ts" target="_blank" rel="noopener" class="Button Gray">Online Demo</a></p> <span class="H-Separator"></span>
<h3 data-anchor="js-shadow-dom" data-toc-title="Shadow DOM Support (CTP)">
<a name="js-shadow-dom" class="anchor"></a>Shadow DOM Support (CTP)
</h3>
<p><a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_shadow_DOM" target="_blank" rel="noopener">Shadow DOM</a> represents one of three Web Components specifications, complemented by
<a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_templates_and_slots" target="_blank" rel="noopener">HTML templates</a> and
<a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements" target="_blank" rel="noopener">Custom Elements</a>. </p>
<p> Shadow DOM allows the attachment of a hidden, separate Document Object Model (DOM) to an element, termed the 'Shadow Host'. This hidden DOM, called the 'Shadow DOM', can contain additional nested Shadow Hosts, forming a structure
known as a Shadow Tree. </p>
<p> It's a direct method to create components with isolated CSS and JavaScript. Many everyday web interfaces use Shadow DOM (a feature available in all major browsers). </p>
<p> This release cycle introduces Shadow DOM support in Angular, React, and Vue as a Community Technology Preview (CTP). Accordingly, you can now use DevExtreme components inside the Shadow DOM of custom HTML elements (Web Components).
</p>
<div class="Attention">
<p><strong>Note</strong>: CTPs includes limitations. Refer to our documentation for additional information:
<a href="https://js.devexpress.com/Angular/Documentation/24_1/Guide/Common/Shadow_DOM/" target="_blank" rel="noopener">Angular</a> |
<a href="https://js.devexpress.com/React/Documentation/24_1/Guide/Common/Shadow_DOM/" target="_blank" rel="noopener">React</a> |
<a href="https://js.devexpress.com/Vue/Documentation/24_1/Guide/Common/Shadow_DOM/" target="_blank" rel="noopener">Vue</a></p>
</div>
<p> Select one of the following supported dev frameworks to explore the capabilities of this new feature: </p>
<p><a href="https://codesandbox.io/p/devbox/devextreme-beta-24-1-datagrid-in-shadow-dom-jqw8zf?file=%2Fsrc%2Fapp%2Fapp.component.ts%3A5%2C1" target="_blank" rel="noopener">Angular</a> |
<a href="https://codesandbox.io/p/sandbox/devextreme-beta-24-1-datagrid-in-shadow-dom-hq2mnm?file=%2FApp.tsx%3A3%2C19" target="_blank" rel="noopener">React</a> |
<a href="https://codesandbox.io/p/sandbox/devextreme-beta-24-1-datagrid-in-shadow-dom-785hvg?file=%2FApp.vue" target="_blank" rel="noopener">Vue</a></p> <span class="H-Separator"></span>
<h3 data-anchor="js-accessibility" data-toc-title="Accessibility">
<a name="js-accessibility" class="anchor"></a>Accessibility
</h3>
<p> v24.1 accessibility-related enhancements include NVDA support for improved keyboard navigation and pronunciation support across the following components: </p>
<ul>
<li>Tabs</li>
<li>TabPanel</li>
<li>TagBox</li>
<li>List</li>
<li>DropDownButton</li>
<li>Calendar</li>
<li>DataGrid with Master-Detail</li>
</ul>
<p> Additionally, <code data-renderer="hljs" class="csharp" data-control="Code-Inline">DataGrid</code> and <code data-renderer="hljs" class="csharp" data-control="Code-Inline">TreeList</code> now meet the Status Messages criterion. </p>
<p> You can now access accessibility compliance (using the <a href="https://www.deque.com/axe/" target="_blank" rel="noopener">AXE®</a> web accessibility evaluation tool) in the following DevExtreme demos: </p>
<p><a href="https://js.devexpress.com/Demos/WidgetsGallery/Demo/DataGrid/Overview/" target="_blank" rel="noopener">Data Grid Overview</a></p> <span class="H-Separator"></span>
<h3 data-anchor="aspnetcore-date-only-time-only" data-toc-title="ASP.NET Core - DateOnly/TimeOnly Type Support">
<a name="aspnetcore-date-only-time-only" class="anchor"></a>ASP.NET Core - DateOnly/TimeOnly Type Support
</h3>
<p> DevExtreme ASP.NET Core DataGrid now supports DateOnly and TimeOnly data types. DateOnly and TimeOnly data types offer the following benefits when compared to the traditional DateTime data type: </p>
<ul>
<li>Usage clarity.</li>
<li>Improved database compatibility.</li>
<li>Less space during serialization.</li>
<li>Ability to mitigate potential errors/inconsistencies related to different time zones.</li>
</ul>
<p> The following DataGrid features support DateOnly and TimeOnly data types: </p>
<ul>
<li>Filtering-related UI elements (filter row, filter panel, search panel, header filter)</li>
<li>Grouping (group interval data operations, both outside and inside a header filter)</li>
<li>Summary (min/max, count)</li>
</ul>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">Razor</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="razor"><span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"grid"</span>></span><span class="hljs-tag"></<span class="hljs-name">div</span>></span>
<span class="hljs-tag"><<span class="hljs-name">script</span>></span><span class="language-javascript">
$(<span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) {
$(<span class="hljs-string">"#grid"</span>).<span class="hljs-title function_">dxDataGrid</span>({
<span class="hljs-attr">columns</span>: [
{
<span class="hljs-attr">dataField</span>: <span class="hljs-string">"orderDateOnly"</span>,
<span class="hljs-attr">dataType</span>: <span class="hljs-string">"date"</span>,
<span class="hljs-attr">headerFilter</span>: {
<span class="hljs-attr">groupInterval</span>: <span class="hljs-string">"quarter"</span>
}
},
{
<span class="hljs-attr">dataField</span>: <span class="hljs-string">"orderTimeOnly"</span>,
<span class="hljs-attr">dataType</span>: <span class="hljs-string">"time"</span>,
},]
});
});
</span><span class="hljs-tag"></<span class="hljs-name">script</span>></span></code></pre>
</div>
</div> <span class="H-Separator"></span>
<h3 data-anchor="aspnetcore-data-validation" data-toc-title="ASP.NET Core - Data Validation">
<a name="aspnetcore-data-validation" class="anchor"></a>ASP.NET Core - Data Validation
</h3>
<h4 anchor="aspnetcore-standalone-editor-validation">
<a name="aspnetcore-standalone-editor-validation" class="anchor visible-anchor" href="#aspnetcore-standalone-editor-validation">#</a>Standalone Editor Validation
</h4>
<p> With this release, you can use <a href="https://docs.devexpress.com/AspNetCore/400574/devextreme-based-controls/concepts/razor-syntax" target="_blank" rel="noopener">Razor syntax</a> (in addition to Model-based method) to add
<a href="https://docs.devexpress.com/AspNetCore/400576/devextreme-based-controls/concepts/data-validation" target="_blank" rel="noopener">validation rules</a> directly to DevExtreme Editors. </p>
<p> This method can be used in the following situations: </p>
<ul>
<li>Modifying validation rules when model changes are impossible, such as when models are shared across views.</li>
<li>Adding extra editors to a view and defining associated validation rules independent of a model.</li>
</ul>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">Razor</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="razor"><span class="hljs-built_in">@(</span><span class="language-csharp">
Html.DevExtreme</span><span class="language-csharp">()</span><span class="language-csharp">.TextBoxFor</span><span class="language-csharp">(m => m.StringProperty)</span><span class="language-csharp">.ValidationRules</span><span class="language-csharp">(tvr => {
tvr.AddRequired</span><span class="language-csharp">()</span><span class="language-csharp">;
})</span><span class="language-csharp">
</span><span class="hljs-built_in">)</span></code></pre>
</div>
</div> <span class="H-Separator"></span>
<h4 anchor="aspnetcore-additionalfields">
<a name="aspnetcore-additionalfields" class="anchor visible-anchor" href="#aspnetcore-additionalfields">#</a>Remote Attribute — AdditionalFields Property Support
</h4>
<p> In ASP.NET Core, the <a href="https://learn.microsoft.com/en-us/aspnet/core/mvc/models/validation?view=aspnetcore-8.0#remote-attribute">Remote</a> attribute facilitates client-side validation. Its
<a href="https://learn.microsoft.com/en-us/aspnet/core/mvc/models/validation?view=aspnetcore-8.0#additional-fields" target="_blank" rel="noopener">AdditionalFields</a> property enables server-based validation of field combinations. </p>
<p> This release introduces support for the <code data-renderer="hljs" class="csharp" data-control="Code-Inline">AdditionalFields</code> option in the DevExtreme DataGrid and TreeList. </p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-aspnetcore-data-validation.png" srcset="/subscriptions/i/24.1/24-1-aspnetcore-data-validation.png 1x, /subscriptions/i/24.1/24-1-aspnetcore-data-validation@2x.png 2x"
alt="AdditionalFields Property Support - ASP.NET Core, DevExpress" width="480" height="336" style="border: none" id="ctl00_ctl00_Content_Content_ctl3553"></div>
<p> The following code snippet validates email addresses in a DataGrid column. When a user enters an email that exists in the database, it determines whether to create a new profile or edit an existing record (refer to RemoteValidation
Controller). To enable this validation, pass the <code data-renderer="hljs" class="csharp" data-control="Code-Inline">ID</code> field to <code data-renderer="hljs" class="csharp" data-control="Code-Inline">AdditionalFields</code>: </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">View</li>
<li>Model</li>
<li>Remote Validation Controller</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="csharp">@(Html.DevExtreme().DataGrid<EmployeeValidation>()
.Editing(editing => {
editing.AllowUpdating(<span class="hljs-literal">true</span>);
editing.AllowAdding(<span class="hljs-literal">true</span>);
})
.Columns(columns => {
columns.AddFor(m => m.ID);
columns.AddFor(m => m.Email);
})
)</code></pre>
</div>
<div class="CodeContainer">
<pre><code data-renderer="hljs" class="csharp"><span class="hljs-keyword">using</span> System.ComponentModel.DataAnnotations;
<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">EmployeeValidation</span> {
<span class="hljs-keyword">public</span> <span class="hljs-built_in">int</span> ID { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
[<span class="hljs-meta">Remote(<span class="hljs-string">"CheckUniqueEmailAddress"</span>, <span class="hljs-string">"RemoteValidation"</span>, AdditionalFields = nameof(ID))</span>]
<span class="hljs-keyword">public</span> <span class="hljs-built_in">string</span> Email { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
}</code></pre>
</div>
<div class="CodeContainer">
<pre><code data-renderer="hljs" class="csharp">[<span class="hljs-meta">HttpPost</span>]
<span class="hljs-function"><span class="hljs-keyword">public</span> JsonResult <span class="hljs-title">CheckUniqueEmailAddress</span>(<span class="hljs-params">EmployeeValidation model</span>)</span> {
<span class="hljs-keyword">var</span> isValid = !db.Employees.Any(emp => {
<span class="hljs-keyword">var</span> <span class="hljs-keyword">equals</span> = <span class="hljs-built_in">string</span>.Equals(emp.Email, model.Email, StringComparison.OrdinalIgnoreCase);
<span class="hljs-keyword">return</span> model.ID != emp.ID &amp;&amp; <span class="hljs-keyword">equals</span>;
});
<span class="hljs-keyword">return</span> Json(isValid);
}</code></pre>
</div>
</div> <span class="H-Separator"></span>
<h3 data-anchor="aspnetcore-richtexteditor" data-toc-title="ASP.NET Core - Rich Text Editor">
<a name="aspnetcore-richtexteditor" class="anchor"></a>ASP.NET Core - Rich Text Editor
</h3>
<h4 anchor="aspnetcore-richedit-table-api">
<a name="aspnetcore-richedit-table-api" class="anchor visible-anchor" href="#aspnetcore-richedit-table-api">#</a>New Table API
</h4><img src="/subscriptions/i/24.1/aspnet-tag.png" srcset="/subscriptions/i/24.1/aspnet-tag.png 1x, /subscriptions/i/24.1/aspnet-tag@2x.png 2x" alt="DevExpress ASP.NET and Blazor Subscription" width="247" height="32"
style="border: none" id="ctl00_ctl00_Content_Content_ctl3570">
<p> With v24.1, the DevExpress <a href="https://docs.devexpress.com/AspNetCore/400373/rich-edit" target="_blank" rel="noopener">Rich Text Editor</a> for ASP.NET Core allows you to modify table layout, decoration, and structure at runtime.
</p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">JavaScript</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="javascript"><span class="hljs-keyword">const</span> columnCount = <span class="hljs-number">5</span>;
<span class="hljs-keyword">const</span> rowCount = <span class="hljs-number">5</span>;
<span class="hljs-keyword">const</span> table = richEdit.<span class="hljs-property">document</span>.<span class="hljs-property">tables</span>.<span class="hljs-title function_">create</span>(<span class="hljs-number">0</span>, columnCount, rowCount);
table.<span class="hljs-property">autoFit</span> = <span class="hljs-literal">false</span>;
table.<span class="hljs-property">styleName</span> = <span class="hljs-string">"Grid Table 5 Dark Accent 1"</span>;
table.<span class="hljs-property">width</span> = { <span class="hljs-attr">type</span>: <span class="hljs-title class_">TableWidthType</span>.<span class="hljs-property">Twips</span>, <span class="hljs-attr">value</span>: <span class="hljs-number">9000</span> };
table.<span class="hljs-property">tableStyleOptions</span> = {
...table.<span class="hljs-property">tableStyleOptions</span>,
<span class="hljs-attr">totalRow</span>: <span class="hljs-literal">true</span>,
<span class="hljs-attr">headerRow</span>: <span class="hljs-literal">true</span>,
}
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i < table.<span class="hljs-property">rows</span>.<span class="hljs-property">count</span>; i++) {
<span class="hljs-keyword">const</span> cells = table.<span class="hljs-property">rows</span>.<span class="hljs-title function_">getByIndex</span>(i)!.<span class="hljs-property">cells</span>;
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> j = <span class="hljs-number">0</span>; j < cells.<span class="hljs-property">count</span>; j++) {
<span class="hljs-keyword">const</span> cell = cells.<span class="hljs-title function_">getByIndex</span>(j)!;
richEdit.<span class="hljs-property">document</span>.<span class="hljs-title function_">insertText</span>(cell.<span class="hljs-property">interval</span>.<span class="hljs-property">start</span>, <span class="hljs-string">`Row <span class="hljs-subst">${i}</span> Cell <span class="hljs-subst">${j}</span>`</span>);
}
}</code></pre>
</div>
</div> <span class="H-Separator"></span>
<h4 anchor="aspnetcore-richedit-html-export-import">
<a name="aspnetcore-richedit-html-export-import" class="anchor visible-anchor" href="#aspnetcore-richedit-html-export-import">#</a>HTML Export/Import
</h4><img src="/subscriptions/i/24.1/aspnet-tag.png" srcset="/subscriptions/i/24.1/aspnet-tag.png 1x, /subscriptions/i/24.1/aspnet-tag@2x.png 2x" alt="DevExpress ASP.NET and Blazor Subscription" width="247" height="32"
style="border: none" id="ctl00_ctl00_Content_Content_ctl3583">
<p> The Rich Text Editor now supports the import and export of documents in HTML format. You can add HTML markup to the main sub-document (insertHtml method overloads), obtain HTML text and markup of the main sub-document (getHtml method
overloads), and download document content to a file in HTML format. </p> <span class="H-Separator"></span>
<h3 data-anchor="devextreme-survey" data-toc-title="Survey - JavaScript & ASP.NET Core">
<a name="devextreme-survey" class="anchor"></a>Survey - JavaScript & ASP.NET Core
</h3>
<h4 anchor=""> Your Feedback Matters! </h4>
<div id="ctl00_ctl00_Content_Content_SurveyContainer" data-control="survey" class="InlineSurvey">
<div data-role="SurveyContent" data-markdown="false" data-partial="false" data-multiple-results="None" data-survey-id="55bdbca6-5d8d-4acf-bc8a-ae9997da4d93" data-auth-required="true"
data-user-data="{"IsLoggedIn":false,"IsEmployee":false,"CustomerId":null}" style="display: none;">
</div>
<div data-role="AuthRequired" style="display: block;"> Please <a href="https://www.devexpress.com/MyAccount/LogIn/?returnUrl=https%3a%2f%2fwww.devexpress.com%2fsubscriptions%2fwhats-new%2f">login</a> to complete the survey. </div>
<div data-role="Loading" style="display: none;">
<img src="../../Content/Editors/ajax-loader.gif" style="border-width:0px;">
</div>
<div data-role="Completed" style="display: none;">
<h3> Survey Completed </h3>
<p class="sys-max-width-md-80 sys-max-width-lg-60"> Thank you for taking the time to complete this survey. Your responses have now been posted. If you want to follow up with additional information, feel free to send us an email at
<a href="mailto:clientservices@devexpress.com">clientservices@devexpress.com</a> anytime. </p>
</div>
<div data-role="AlreadyPassed" style="display: none;">
<h3> You've Already Completed This Survey </h3>
<p class="sys-max-width-md-80 sys-max-width-lg-60"> Our records show that you have already completed this survey. If you want to follow up with additional information, send us an email at
<a href="mailto:clientservices@devexpress.com">clientservices@devexpress.com</a>. </p>
</div>
<div data-role="Expired" style="display: none;">
<h3> This survey has expired </h3>
<p>If you want to share your feedback or request new functionality, please submit a new support ticket via the <a href="https://supportcenter.devexpress.com/">DevExpress Support Center</a>. We’ll be happy to follow up.</p>
</div>
</div>
<h2 class="SectionHeader" data-anchor="blazor" data-toc-title="Blazor">
<a data-whatsnew-platform="blazor" name="blazor" class="anchor"></a>Blazor UI Components v24.1
</h2>
<div class="WhatsNewTOC grid sys-visibility-hidden sys-visibility-hidden sys-visibility-sm-shown">
<div class="row">
<div class="col-sm-6 col-md-3 col-order-1">
<p><a href="#blazor-treelist"><span>New TreeList (CTP)</span></a></p>
<p><a href="#blazor-htmleditor"><span>New HTML Editor</span></a></p>
<p><a href="#blazor-pdfviewer"><span>New PDF Viewer (CTP)</span></a></p>
<p><a href="#blazor-map"><span>New Map</span></a></p>
<p><a href="#blazor-polarchart"><span>New Polar Chart</span></a></p>
<p><a href="#blazor-daterangepicker"><span>New Date Range Picker</span></a></p>
<p><a href="#blazor-dropdownbox"><span>New DropDown Box</span></a></p>
</div>
<div class="col-sm-6 col-md-3 col-sm-order-3 col-md-order-2">
<p><a href="#blazor-fileinput"><span>New File Input</span></a></p>
<p><a href="#blazor-drawer"><span>New Drawer</span></a></p>
<p><a href="#blazor-toast"><span>New Toast</span></a></p>
<p><a href="#blazor-progressbar"><span>New Progress Bar</span></a></p>
<p><a href="#blazor-bargauge"><span>New Bar Gauge</span></a></p>
<p><a href="#blazor-sparkline"><span>New Sparkline</span></a></p>
<p><a href="#blazor-rendering-engine"><span>New Rendering Engine</span></a></p>
</div>
<div class="column-break sm">
</div>
<div class="col-sm-6 col-md-3 col-sm-order-2 col-md-order-3">
<p><a href="#blazor-keyboard-support"><span>Keyboard Support</span></a></p>
<p><a href="#blazor-project-templates"><span>Project Templates</span></a></p>
<p><a href="#blazor-grid"><span>Grid</span></a></p>
<p><a href="#blazor-charts"><span>Charts</span></a></p>
<p><a href="#blazor-combobox-tagbox"><span>New ComboBox and TagBox</span></a></p>
<p><a href="#blazor-listbox"><span>List Box</span></a></p>
<p><a href="#blazor-datetime-editors"><span>Date Edit & Time Edit</span></a></p>
</div>
<div class="col-sm-6 col-md-3 col-order-4">
<p><a href="#blazor-file-management"><span>File Management</span></a></p>
<p><a href="#blazor-form-layout"><span>Form Layout</span></a></p>
<p><a href="#blazor-richtexteditor"><span>Rich Text Editor</span></a></p>
<p><a href="#blazor-scheduler"><span>Scheduler</span></a></p>
<p><a href="#blazor-window-popup"><span>Window and Popup</span></a></p>
<p><a href="#blazor-survey"><span>Survey - Blazor</span></a></p>
</div>
</div>
</div>
<div class="Attention">
<p><strong>Your feedback matters.</strong><br> Please, review the description of <strong>Blazor</strong>-related features below and leave your feedback at the end of the section. </p>
<p><a href="#blazor-survey">Go to the survey now.</a></p>
</div>
<h3 data-anchor="blazor-treelist" data-toc-title="New TreeList (CTP)">
<a name="blazor-treelist" class="anchor"></a>New TreeList (CTP)
</h3>
<p> Our new Blazor <a href="https://docs.devexpress.com/Blazor/404942/components/treelist?v=24.1" target="_blank" rel="noopener">TreeList</a> allows you to organize, display, and navigate hierarchical data with absolute ease. The
component ships with the following integrated capabilities: </p>
<ul>
<li>Data Sorting</li>
<li>Filter Row with Auto-Generated Editors</li>
<li>Total Summaries</li>
<li>Single and Multiple Node Selection</li>
<li>Focused Row</li>
<li>Header Bands</li>
<li>Paging and Scrolling</li>
<li>Virtual Scrolling</li>
<li>Toolbar</li>
<li>Keyboard Support</li>
</ul>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-blazor-treelist.png" srcset="/subscriptions/i/24.1/24-1-blazor-treelist.png 1x, /subscriptions/i/24.1/24-1-blazor-treelist@2x.png 2x" alt="Blazor TreeList, DevExpress"
width="1052" height="448" style="border: none" id="ctl00_ctl00_Content_Content_ctl3952"></div>
<p><a href="https://demos.devexpress.com/blazor/TreeList" target="_blank" rel="noopener" class="Button Gray">Online Demo</a></p>
<p> You will notice that the DevExpress Blazor TreeList and Grid UI components look and behave in a similar manner. This is not a coincidence. Our Blazor TreeList and Grid use the same rendering engine and rely upon common
logic/algorithms. Thanks to commonalities between the components, we are in position to add new functionality to both of components simultaneously in future release cycles. </p> <span class="H-Separator"></span>
<h4 anchor="blazor-grid-bind-to-flat-data">
<a name="blazor-grid-bind-to-flat-data" class="anchor visible-anchor" href="#blazor-grid-bind-to-flat-data">#</a>Bind to Flat Data
</h4>
<p> Our Blazor TreeList component can be bound to any traditional data source. Since the TreeList is designed to display information using a tree structure, its data source must meet specific requirements. If a data source contains flat
data, two additional fields are necessary to build the appropriate tree structure: </p>
<ul>
<li>A field that contains a node’s unique identifier. Assign this field to the <a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxTreeList.KeyFieldName?v=24.1" target="_blank" rel="noopener">KeyFieldName</a> property.</li>
<li>A field that contains the unique identifier of a node’s parent. Assign this field to the
<a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxTreeList.ParentKeyFieldName?v=24.1" target="_blank" rel="noopener">ParentKeyFieldName</a> property.</li>
</ul>
<p> The following example binds the Blazor TreeList component to a flat data source: </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">Razor</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="razor"><span class="hljs-built_in">@inject</span><span class="hljs-type"> IEmployeeTaskDataProvider EmployeeTaskDataProvider</span>
<span class="hljs-tag"><<span class="hljs-name">DxTreeList</span> <span class="hljs-attr">Data</span>=<span class="hljs-string">"<span class="hljs-built_in">@</span><span class="language-csharp">TreeListData</span>"</span>
<span class="hljs-attr">KeyFieldName</span>=<span class="hljs-string">"Id"</span>
<span class="hljs-attr">ParentKeyFieldName</span>=<span class="hljs-string">"ParentId"</span>></span>
<span class="hljs-tag"><<span class="hljs-name">Columns</span>></span>
<span class="hljs-tag"><<span class="hljs-name">DxTreeListDataColumn</span> <span class="hljs-attr">FieldName</span>=<span class="hljs-string">"Name"</span> /></span>
<span class="hljs-tag"><<span class="hljs-name">DxTreeListDataColumn</span> <span class="hljs-attr">FieldName</span>=<span class="hljs-string">"EmployeeName"</span><span class="hljs-string">/</span>></span>
<span class="hljs-tag"><<span class="hljs-name">DxTreeListDataColumn</span> <span class="hljs-attr">FieldName</span>=<span class="hljs-string">"StartDate"</span> /></span>
<span class="hljs-tag"><<span class="hljs-name">DxTreeListDataColumn</span> <span class="hljs-attr">FieldName</span>=<span class="hljs-string">"DueDate"</span> /></span>
<span class="hljs-tag"></<span class="hljs-name">Columns</span>></span>
<span class="hljs-tag"></<span class="hljs-name">DxTreeList</span>></span>
<span class="hljs-built_in">@code {</span><span class="language-csharp">
List</span><span class="hljs-tag"><<span class="hljs-name">EmployeeTask</span>></span><span class="language-csharp"> TreeListData { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
<span class="hljs-function"><span class="hljs-keyword">protected</span> <span class="hljs-keyword">override</span> <span class="hljs-keyword">void</span> <span class="hljs-title">OnInitialized</span> ()</span> {
TreeListData = EmployeeTaskDataProvider.GenerateData();
}
</span><span class="hljs-built_in">}</span></code></pre>
</div>
</div> <span class="H-Separator"></span>
<h4 anchor="blazor-treelist-bind-to-server-data">
<a name="blazor-treelist-bind-to-server-data" class="anchor visible-anchor" href="#blazor-treelist-bind-to-server-data">#</a>Bind to Server-Side Data
</h4>
<p> You can also bind the DevExpress Blazor TreeList component to our <a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.GridDevExtremeDataSource-1?v=24.1" target="_blank" rel="noopener">DevExtremeDataSource</a>. This data
source allows you to improve TreeList performance when binding large data sets for the following reasons: </p>
<ul>
<li>The TreeList loads child nodes on demand (when user expands a node).</li>
<li><a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.GridDevExtremeDataSource-1?v=24.1" target="_blank" rel="noopener">DevExtremeDataSource</a> performs data filtering operations on the server.</li>
</ul>
<p> To bind the component to <a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.GridDevExtremeDataSource-1?v=24.1" target="_blank" rel="noopener">DevExtremeDataSource</a>, you must: </p>
<ul>
<li>Assign a <a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.GridDevExtremeDataSource-1?v=24.1" target="_blank" rel="noopener">GridDevExtremeDataSource</a> instance to the
<a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxTreeList.Data?v=24.1" target="_blank" rel="noopener">Data</a> property</li>
<li>Specify <a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxTreeList.KeyFieldName?v=24.1" target="_blank" rel="noopener">KeyFieldName</a> and
<a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxTreeList.ParentKeyFieldName?v=24.1" target="_blank" rel="noopener">ParentKeyFieldName</a> properties.</li>
<li>Specify the <a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxTreeList.HasChildrenFieldName?v=24.1" target="_blank" rel="noopener">HasChildrenFieldName</a> property. This property helps determine whether a node
includes children and if the node requires an expand button.</li>
</ul> <span class="H-Separator"></span>
<h4 anchor="blazor-treelist-bind-to-hierarchical-data">
<a name="blazor-treelist-bind-to-hierarchical-data" class="anchor visible-anchor" href="#blazor-treelist-bind-to-hierarchical-data">#</a>Bind to Hierarchical Data
</h4>
<p> If each node in your data source includes a field with a list of child nodes, assign the field’s name to the
<a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxTreeList.ChildrenFieldName?v=24.1" target="_blank" rel="noopener">ChildrenFieldName</a> property and bind the
<a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxTreeList.Data?v=24.1" target="_blank" rel="noopener">Data</a> property to the data source: </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">Razor</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="razor"><span class="hljs-built_in">@inject</span><span class="hljs-type"> ISpaceObjectDataProvider SpaceObjectDataProvider</span>
<span class="hljs-tag"><<span class="hljs-name">DxTreeList</span> <span class="hljs-attr">Data</span>=<span class="hljs-string">"<span class="hljs-built_in">@</span><span class="language-csharp">TreeListData</span>"</span>
<span class="hljs-attr">ChildrenFieldName</span>=<span class="hljs-string">"Satellites"</span>></span>
<span class="hljs-tag"><<span class="hljs-name">Columns</span>></span>
<span class="hljs-tag"><<span class="hljs-name">DxTreeListDataColumn</span> <span class="hljs-attr">FieldName</span>=<span class="hljs-string">"Name"</span><span class="hljs-string">/</span>></span>
<span class="hljs-tag"><<span class="hljs-name">DxTreeListDataColumn</span> <span class="hljs-attr">FieldName</span>=<span class="hljs-string">"TypeOfObject"</span> <span class="hljs-attr">Caption</span>=<span class="hljs-string">"Type"</span><span class="hljs-string">/</span>></span>
<span class="hljs-tag"><<span class="hljs-name">DxTreeListDataColumn</span> <span class="hljs-attr">FieldName</span>=<span class="hljs-string">"Mass"</span> <span class="hljs-attr">Caption</span>=<span class="hljs-string">"Mass, kg"</span><span class="hljs-string">/</span>></span>
<span class="hljs-tag"><<span class="hljs-name">DxTreeListDataColumn</span> <span class="hljs-attr">FieldName</span>=<span class="hljs-string">"MeanRadius"</span> <span class="hljs-attr">Caption</span>=<span class="hljs-string">"Radius, km"</span><span class="hljs-string">/</span>></span>
<span class="hljs-tag"></<span class="hljs-name">Columns</span>></span>
<span class="hljs-tag"></<span class="hljs-name">DxTreeList</span>></span>
<span class="hljs-built_in">@code {</span><span class="language-csharp">
List</span><span class="hljs-tag"><<span class="hljs-name">SpaceObject</span>></span><span class="language-csharp"> TreeListData { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
<span class="hljs-function"><span class="hljs-keyword">protected</span> <span class="hljs-keyword">override</span> <span class="hljs-keyword">void</span> <span class="hljs-title">OnInitialized</span> ()</span> {
TreeListData = SpaceObjectDataProvider.GenerateData();
}
</span><span class="hljs-built_in">}</span></code></pre>
</div>
</div>
<p> Alternatively, you can assign a collection of root nodes to the <a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxTreeList.Data?v=24.1" target="_blank" rel="noopener">Data</a> property and handle the
<a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxTreeList.ChildrenLoading?v=24.1" target="_blank" rel="noopener">ChildrenLoading</a> event to populate nodes with children. In the event handler, use the
<a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.TreeListChildrenLoadingEventArgs.Parent?v=24.1" target="_blank" rel="noopener">Parent</a> argument to determine the processed node and assign this node’s children to the
<a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.TreeListChildrenLoadingEventArgs.Children?v=24.1" target="_blank" rel="noopener">Children</a> property. </p> <span class="H-Separator"></span>
<h4 anchor="blazor-treelist-load-data-on-demand">
<a name="blazor-treelist-load-data-on-demand" class="anchor visible-anchor" href="#blazor-treelist-load-data-on-demand">#</a>Load Data on Demand
</h4>
<p> The DevExpress Blazor TreeList allows you to initially load only root nodes and retrieve node children when a node is expanded for the first time. To switch the component to on demand mode, follow the steps below: </p>
<ul>
<li>Assign root data items to the <a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxTreeList.Data?v=24.1" target="_blank" rel="noopener">Data</a> property.</li>
<li>Specify the <a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxTreeList.HasChildrenFieldName?v=24.1" target="_blank" rel="noopener">HasChildrenFieldName</a> property.</li>
<li>Handle the <a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxTreeList.ChildrenLoadingOnDemand?v=24.1" target="_blank" rel="noopener">ChildrenLoadingOnDemand</a> event. In the event handler, use the
<a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.TreeListChildrenLoadingEventArgs.Parent?v=24.1" target="_blank" rel="noopener">Parent</a> argument to determine the processed node and assign the node’s children to the
<a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.TreeListChildrenLoadingEventArgs.Children?v=24.1" target="_blank" rel="noopener">Children</a> event argument.</li>
</ul>
<p> The following example loads TreeList data on demand: </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">Razor</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="razor"><span class="hljs-built_in">@inject</span><span class="hljs-type"> FileSystemDataProvider FileSystemDataProvider</span>
<span class="hljs-tag"><<span class="hljs-name">DxTreeList</span> <span class="hljs-attr">Data</span>=<span class="hljs-string">"TreeListData"</span>
<span class="hljs-attr">HasChildrenFieldName</span>=<span class="hljs-string">"HasChildren"</span>
<span class="hljs-attr">ChildrenLoadingOnDemand</span>=<span class="hljs-string">"TreeList_ChildrenLoadingOnDemand"</span>></span>
<span class="hljs-tag"><<span class="hljs-name">Columns</span>></span>
<span class="hljs-tag"><<span class="hljs-name">DxTreeListDataColumn</span> <span class="hljs-attr">FieldName</span>=<span class="hljs-string">"Name"</span> /></span>
<span class="hljs-tag"><<span class="hljs-name">DxTreeListDataColumn</span> <span class="hljs-attr">FieldName</span>=<span class="hljs-string">"Type"</span> /></span>
<span class="hljs-tag"><<span class="hljs-name">DxTreeListDataColumn</span> <span class="hljs-attr">FieldName</span>=<span class="hljs-string">"DateModified"</span> /></span>
<span class="hljs-tag"><<span class="hljs-name">DxTreeListDataColumn</span> <span class="hljs-attr">FieldName</span>=<span class="hljs-string">"Size"</span> /></span>
<span class="hljs-tag"></<span class="hljs-name">Columns</span>></span>
<span class="hljs-tag"></<span class="hljs-name">DxTreeList</span>></span>
<span class="hljs-built_in">@code {</span><span class="language-csharp">
<span class="hljs-built_in">object</span> TreeListData { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
<span class="hljs-function"><span class="hljs-keyword">protected</span> <span class="hljs-keyword">override</span> <span class="hljs-keyword">async</span> Task <span class="hljs-title">OnInitializedAsync</span>()</span> {
Data = <span class="hljs-keyword">await</span> FileSystemDataProvider.GetRootItemsAsync();
}
<span class="hljs-function">Task <span class="hljs-title">TreeList_ChildrenLoadingOnDemand</span>(<span class="hljs-params">TreeListChildrenLoadingOnDemandEventArgs e</span>)</span> {
<span class="hljs-keyword">var</span> item = e.Parent <span class="hljs-keyword">as</span> FileSystemDataItem;
e.Children = item.Children;
<span class="hljs-keyword">return</span> Task.CompletedTask;
}
</span><span class="hljs-built_in">}</span></code></pre>
</div>
</div> <span class="H-Separator"></span>
<h3 data-anchor="blazor-htmleditor" data-toc-title="New HTML Editor">
<a name="blazor-htmleditor" class="anchor"></a>New HTML Editor
</h3>
<p> Our Blazor <a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxHtmlEditor?v=24.1" target="_blank" rel="noopener">HTML Editor</a> allows you to format/display text and visual content and store it as HTML or Markdown. Users
can apply inline formatting and modify font, size, and color as needs dictate. Additionally, the DevExpress Blazor HTML Editor offers the following integrated features: </p>
<ul>
<li>Block formatting, including headings, text alignment, lists (bullet and numbered), code blocks, and quotes.</li>
<li>Variables support (for example, {{companyName}}): Among other use cases, this capability can be used to generate dynamic email content.</li>
<li>Toolbar with adaptive layout support.</li>
<li>Built-in toolbar customization.</li>
<li>Image Insert: You can upload an image from the local file system or specify a URL.</li>
<li>Table support.</li>
<li>Mentions support.</li>
</ul>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-blazor-html-editor.png" srcset="/subscriptions/i/24.1/24-1-blazor-html-editor.png 1x, /subscriptions/i/24.1/24-1-blazor-html-editor@2x.png 2x"
alt="Blazor HTML Editor, DevExpress" width="1050" height="434" style="border: none" id="ctl00_ctl00_Content_Content_ctl4040"></div>
<p><a href="https://demos.devexpress.com/blazor/HtmlEditor" target="_blank" rel="noopener" class="Button Gray">Online Demo</a></p> <span class="H-Separator"></span>
<h3 data-anchor="blazor-pdfviewer" data-toc-title="New PDF Viewer (CTP)">
<a name="blazor-pdfviewer" class="anchor"></a>New PDF Viewer (CTP)
</h3>
<p> The new DevExpress <a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.PdfViewer.DxPdfViewer?v=24.1" target="_blank" rel="noopener">Blazor PDF Viewer</a> component can display PDF file content directly in your
DevExpress-powered Blazor app. The component allows you to navigate through the document, set zoom level, print, and download the document. Additionally, the CTP version of the Blazor PDF Viewer includes a single-page preview and
toolbar customization option (such as rearranging, grouping, hiding, and adding items) </p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-blazor-pdf-viewer-ctp.png" srcset="/subscriptions/i/24.1/24-1-blazor-pdf-viewer-ctp.png 1x, /subscriptions/i/24.1/24-1-blazor-pdf-viewer-ctp@2x.png 2x"
alt="Blazor PDF Viewer, DevExpress" width="1054" height="996" style="border: none" id="ctl00_ctl00_Content_Content_ctl4054"></div>
<p><a href="https://demos.devexpress.com/blazor/PdfViewer" target="_blank" rel="noopener" class="Button Gray">Online Demo</a></p> <span class="H-Separator"></span>
<h3 data-anchor="blazor-map" data-toc-title="New Map">
<a name="blazor-map" class="anchor"></a>New Map
</h3>
<p> The DevExpress <a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxMap?v=24.1" target="_blank" rel="noopener">Blazor Map</a> component can display geo maps with markers and route info within your DevExpress-powered Blazor
web app. The component retrieves relevant data from a GIS service (Bing, Google, or GoogleStatic - requires application authentication with an appropriate API key) and ships with the following capabilities: </p>
<ul>
<li>Marker/route configuration and customization options.</li>
<li>Built-in map navigation and type controls.</li>
<li>Manual map adjustment (set <a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxMap.Zoom?v=24.1" target="_blank" rel="noopener">Zoom</a> and
<a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxMapCenter?v=24.1" target="_blank" rel="noopener">MapCenter</a>).</li>
<li>Map and marker "click" support.</li>
</ul>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-blazor-new-map.png" srcset="/subscriptions/i/24.1/24-1-blazor-new-map.png 1x, /subscriptions/i/24.1/24-1-blazor-new-map@2x.png 2x" alt="Blazor Map Control, DevExpress"
width="1052" height="518" style="border: none" id="ctl00_ctl00_Content_Content_ctl4069"></div>
<p><a href="https://demos.devexpress.com/blazor/Map" target="_blank" rel="noopener" class="Button Gray">Online Demo</a></p> <span class="H-Separator"></span>
<h3 data-anchor="blazor-polarchart" data-toc-title="New Polar Chart">
<a name="blazor-polarchart" class="anchor"></a>New Polar Chart
</h3>
<p> The DevExpress <a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxPolarChart-1?v=24.1" target="_blank" rel="noopener">Polar Chart for Blazor</a> allows you to visualize data within a polar coordinate system - where each
point on a plane is determined by the distance from the center and the angle from a fixed direction. The DevExpress Blazor Polar Chart component ships with the following capabilities: </p>
<ul>
<li>Multiple series types: line, area, bar, stacked bar, and scatter.</li>
<li>Continuous, discrete, and logarithmic axis value support.</li>
<li>Spider web mode.</li>
<li>Chart element customization: labels, tooltips, legend, and many more.</li>
</ul>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-blazor-polar-chart.png" srcset="/subscriptions/i/24.1/24-1-blazor-polar-chart.png 1x, /subscriptions/i/24.1/24-1-blazor-polar-chart@2x.png 2x"
alt="Blazor Polar Chart, DevExpress" width="1054" height="410" style="border: none" id="ctl00_ctl00_Content_Content_ctl4084"></div>
<p><a href="https://demos.devexpress.com/blazor/ChartPolarContinuousData" target="_blank" rel="noopener" class="Button Gray">Online Demo</a></p> <span class="H-Separator"></span>
<h3 data-anchor="blazor-daterangepicker" data-toc-title="New Date Range Picker">
<a name="blazor-daterangepicker" class="anchor"></a>New Date Range Picker
</h3>
<p> The DevExpress <a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxDateRangePicker-1?v=24.1" target="_blank" rel="noopener">Date Range Picker</a> for Blazor allows you to select a range of dates within a single calendar
dropdown. The component ships with the following integrated capabilities: </p>
<ul>
<li>Minimum and maximum dates</li>
<li>Special date highlighting</li>
<li>Selected date formatting API</li>
<li>Input validation</li>
<li>Clear button</li>
<li>Nullable date support and placeholder</li>
<li>Automatic support for browser time zone and localization</li>
</ul>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-blazor-new-data-range-picker.png" srcset="/subscriptions/i/24.1/24-1-blazor-new-data-range-picker.png 1x, /subscriptions/i/24.1/24-1-blazor-new-data-range-picker@2x.png 2x"
alt="Blazor Date Range Picker, DevExpress" width="724" height="377" style="border: none" id="ctl00_ctl00_Content_Content_ctl4099"></div>
<p><a href="https://demos.devexpress.com/blazor/DateRangePicker" target="_blank" rel="noopener" class="Button Gray">Online Demo</a></p> <span class="H-Separator"></span>
<h3 data-anchor="blazor-dropdownbox" data-toc-title="New DropDown Box">
<a name="blazor-dropdownbox" class="anchor"></a>New DropDown Box
</h3>
<h4 anchor="">
</h4>
<p> The DevExpress <a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxDropDownBox?v=24.1" target="_blank" rel="noopener">Blazor DropDown Box</a> is a customizable editor - designed to display/use a variety of UI elements
within its drop-down window: from simple lists and trees, to grids, or any combination therein. You can assign an editor value programmatically based on page interactions. </p>
<p> The following code snippet adds the DevExpress Blazor Grid to the DropDown Box popup. </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">Razor</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="razor"><span class="hljs-tag"><<span class="hljs-name">DxDropDownBox</span> <span class="hljs-attr">Value</span>=<span class="hljs-string">"Value"</span> <span class="hljs-attr">QueryDisplayText</span>=<span class="hljs-string">"QueryText"</span>></span>
<span class="hljs-tag"><<span class="hljs-name">DropDownBodyTemplate</span>></span>
<span class="hljs-tag"><<span class="hljs-name">DxGrid</span> <span class="hljs-attr">Data</span>=<span class="hljs-string">"<span class="hljs-built_in">@</span><span class="language-csharp">GridData</span>"</span> <span class="hljs-attr">ShowSearchBox</span>=<span class="hljs-string">"true"</span> <span class="hljs-attr">SelectedDataItem</span>=<span class="hljs-string">"<span class="hljs-built_in">@</span><span class="language-csharp">Value</span>"</span>
<span class="hljs-attr">SelectedDataItemChanged</span>=<span class="hljs-string">"item => GridSelectedDataItemChanged(item, context.DropDownBox)"</span> <span class="hljs-attr">...</span>/></span>
<span class="hljs-tag"></<span class="hljs-name">DropDownBodyTemplate</span>></span>
<span class="hljs-tag"></<span class="hljs-name">DxDropDownBox</span>></span>
<span class="hljs-built_in">@code {</span><span class="language-csharp">
Customer Value { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
IEnumerable</span><span class="hljs-tag"><<span class="hljs-name">object</span>></span><span class="language-csharp"> GridData { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
<span class="hljs-function"><span class="hljs-built_in">string</span> <span class="hljs-title">QueryText</span>(<span class="hljs-params">DropDownBoxQueryDisplayTextContext arg</span>)</span> {
<span class="hljs-keyword">if</span>(arg.Value <span class="hljs-keyword">is</span> Customer <span class="hljs-keyword">value</span>)
<span class="hljs-keyword">return</span> <span class="hljs-keyword">value</span>.ContactName;
<span class="hljs-keyword">return</span> <span class="hljs-built_in">string</span>.Empty;
}
<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">GridSelectedDataItemChanged</span>(<span class="hljs-params"><span class="hljs-built_in">object</span> item, IDropDownBox dropDownBox</span>)</span> {
Value = item <span class="hljs-keyword">as</span> Customer;
dropDownBox.HideDropDown();
}
</span><span class="hljs-built_in">}</span></code></pre>
</div>
</div>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-blazor-new-dropdown-box-1.png" srcset="/subscriptions/i/24.1/24-1-blazor-new-dropdown-box-1.png 1x, /subscriptions/i/24.1/24-1-blazor-new-dropdown-box-1@2x.png 2x"
alt="Blazor DropDown Box, DevExpress" width="826" height="423" style="border: none" id="ctl00_ctl00_Content_Content_ctl4117"></div>
<p> The DropDown Box' value is not limited to a single object. It can be a collection of objects (for those looking to implement a multi-selection editor): </p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-blazor-new-dropdown-box-2.png" srcset="/subscriptions/i/24.1/24-1-blazor-new-dropdown-box-2.png 1x, /subscriptions/i/24.1/24-1-blazor-new-dropdown-box-2@2x.png 2x"
alt="Blazor DropDown Box with Multi-Select Option, DevExpress" width="505" height="276" style="border: none" id="ctl00_ctl00_Content_Content_ctl4120"></div>
<p> Or even a composite data item generated based on user selection made within the popup: </p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-blazor-new-dropdown-box-3.png" srcset="/subscriptions/i/24.1/24-1-blazor-new-dropdown-box-3.png 1x, /subscriptions/i/24.1/24-1-blazor-new-dropdown-box-3@2x.png 2x"
alt="Blazor DropDown Box - Composite Data, DevExpress" width="826" height="505" style="border: none" id="ctl00_ctl00_Content_Content_ctl4123"></div>
<p><a href="https://demos.devexpress.com/blazor/DropDownBox" target="_blank" rel="noopener" class="Button Gray">Online Demo</a></p> <span class="H-Separator"></span>
<h3 data-anchor="blazor-fileinput" data-toc-title="New File Input">
<a name="blazor-fileinput" class="anchor"></a>New File Input
</h3>
<p> Our new <a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxFileInput?v=24.1" target="_blank" rel="noopener">Blazor File Input</a> component allows you to introduce file upload functionality to your Blazor app without
creating a separate Web API project with an upload controller. </p> <p></p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-blazor-file-input.png" srcset="/subscriptions/i/24.1/24-1-blazor-file-input.png 1x, /subscriptions/i/24.1/24-1-blazor-file-input@2x.png 2x" alt="Blazor File Input, DevExpress"
width="983" height="396" style="border: none" id="ctl00_ctl00_Content_Content_ctl4139"></div>
<p></p> <p> Our Blazor File Input control supports multiple upload modes (<code data-renderer="hljs" class="csharp" data-control="Code-Inline">Instant</code> and <code data-renderer="hljs" class="csharp"
data-control="Code-Inline">OnButtonClick</code>), can upload multiple files simultaneously, and allows you to validate file size and extension both on the client and server. </p>
<p> Handle the <a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxFileInput.FilesUploading?v=24.1" target="_blank" rel="noopener">FilesUploading</a> event to upload selected files. For each file, the event supplies a Stream
you can open to read file content. Once the read operation is complete, you can send the file to another destination, save it to the file system, or display the file content on a web page. </p>
<p> The following code snippet configures FileInput to upload files to a specified folder: </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">Razor</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="razor"><span class="hljs-tag"><<span class="hljs-name">DxFileInput</span> <span class="hljs-attr">FilesUploading</span>=<span class="hljs-string">"OnFilesUploading"</span> /></span>
<span class="hljs-built_in">@code {</span><span class="language-csharp">
<span class="hljs-function"><span class="hljs-keyword">async</span> Task <span class="hljs-title">OnFilesUploading</span>(<span class="hljs-params">FilesUploadingEventArgs args</span>)</span> {
<span class="hljs-keyword">foreach</span> (<span class="hljs-keyword">var</span> file <span class="hljs-keyword">in</span> args.Files) {
Stream? stream = <span class="hljs-literal">default</span>;
<span class="hljs-keyword">var</span> filePath = <span class="hljs-string">"full path to the uploaded file"</span>;
FileStream fs = <span class="hljs-keyword">new</span>(filePath, FileMode.Create);
<span class="hljs-keyword">try</span> {
<span class="hljs-keyword">if</span>(IsValidFile(file)) {
stream = file.OpenReadStream(<span class="hljs-built_in">int</span>.MaxValue);
<span class="hljs-keyword">await</span> stream.CopyToAsync(fs);
}
}
<span class="hljs-keyword">catch</span> (Exception ex) {
<span class="hljs-keyword">if</span> (file.CancellationTokenSource.IsCancellationRequested)
<span class="hljs-comment">// Handle the cancel action here</span>
}
<span class="hljs-keyword">finally</span> {
<span class="hljs-keyword">await</span> fs.FlushAsync();
fs.Close();
<span class="hljs-keyword">if</span> (stream != <span class="hljs-literal">null</span>)
stream.Close();
}
}
}
</span><span class="hljs-built_in">}</span></code></pre>
</div>
</div>
<div class="Attention">
<p class="sys-h-align-left"><strong>Note</strong>: Before adding file upload capabilities to your Blazor app, make certain to institute necessary security-related processes (to avoid risks and control unauthorized file operations). </p>
</div>
<p><a href="https://demos.devexpress.com/blazor/FileInput" target="_blank" rel="noopener" class="Button Gray">Online Demo</a></p> <span class="H-Separator"></span>
<h3 data-anchor="blazor-drawer" data-toc-title="New Drawer">
<a name="blazor-drawer" class="anchor"></a>New Drawer
</h3>
<p> Our new <a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxDrawer?v=24.1" target="_blank" rel="noopener">Blazor Drawer</a> component allows you to add a "dismissible" navigation side panel to your web application. The
control includes the following features: </p>
<ul>
<li>Left-side and right-side position.</li>
<li>Overlap and shrink display modes.</li>
<li>The minimized drawer state.</li>
<li>Header, body, and footer templates.</li>
</ul> <p></p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-blazor-drawer.png" srcset="/subscriptions/i/24.1/24-1-blazor-drawer.png 1x, /subscriptions/i/24.1/24-1-blazor-drawer@2x.png 2x" alt="Blazor Drawer, DevExpress" width="1030"
height="480" style="border: none" id="ctl00_ctl00_Content_Content_ctl4176"></div>
<p></p>
<p><a href="https://demos.devexpress.com/blazor/Drawer" target="_blank" rel="noopener" class="Button Gray">Online Demo</a></p> <span class="H-Separator"></span>
<h3 data-anchor="blazor-toast" data-toc-title="New Toast">
<a name="blazor-toast" class="anchor"></a>New Toast
</h3>
<p> Our new <a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxToast?v=24.1" target="_blank" rel="noopener">Blazor Toast</a> component allows you to notify users about processes and events. Notification messages can remain
visible until a user clicks the close button or closed automatically after a predetermined amount of time. The DevExpress Blazor Toast component supports four theme modes (Dark, Light, Pastel, and Saturated) and the following
notification styles: </p>
<ul>
<li>Danger</li>
<li>Info</li>
<li>Primary</li>
<li>Success</li>
<li>Warning</li>
</ul>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-blazor-toast.png" srcset="/subscriptions/i/24.1/24-1-blazor-toast.png 1x, /subscriptions/i/24.1/24-1-blazor-toast@2x.png 2x" alt="Blazor Toast, DevExpress" width="412"
height="500" style="border: none" id="ctl00_ctl00_Content_Content_ctl4191"></div>
<p> You can place a <code data-renderer="hljs" class="csharp" data-control="Code-Inline">DxToast</code> component in markup and call the
<a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxToast.Show?v=24.1" target="_blank" rel="noopener">Show</a> method to display it. </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">Razor</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="razor"><span class="hljs-tag"><<span class="hljs-name">DxToastProvider</span> <span class="hljs-attr">Name</span>=<span class="hljs-string">"ToastContainer"</span> /></span>
<span class="hljs-tag"><<span class="hljs-name">DxToast</span> @<span class="hljs-attr">ref</span>=<span class="hljs-string">toast</span> <span class="hljs-attr">Text</span>=<span class="hljs-string">"The process has been completed."</span> <span class="hljs-attr">ProviderName</span>=<span class="hljs-string">"ToastContainer"</span> /></span>
<span class="hljs-built_in">@code {</span><span class="language-csharp">
DxToast toast;
<span class="hljs-function"><span class="hljs-keyword">protected</span> <span class="hljs-keyword">override</span> <span class="hljs-keyword">void</span> <span class="hljs-title">OnAfterRender</span>(<span class="hljs-params"><span class="hljs-built_in">bool</span> firstRender</span>)</span> {
toast.Show();
}
</span><span class="hljs-built_in">}</span>
<span class="hljs-tag"></<span class="hljs-name">lang</span>></span>
<span class="hljs-tag"></<span class="hljs-name">code2</span>></span>
<span class="hljs-tag"><<span class="hljs-name">para</span>></span>
Alternatively, use the notification service to create toasts at runtime.
<span class="hljs-tag"></<span class="hljs-name">para</span>></span>
<span class="hljs-tag"><<span class="hljs-name">code2</span>></span>
<span class="hljs-tag"><<span class="hljs-name">lang</span> <span class="hljs-attr">brush</span>=<span class="hljs-string">"razor"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"Razor"</span>></span>
<span class="hljs-tag"><<span class="hljs-name">DxToastProvider</span> <span class="hljs-attr">Name</span>=<span class="hljs-string">"ToastContainer"</span> /></span>
<span class="hljs-built_in">@code {</span><span class="language-csharp">
[<span class="hljs-meta">Inject</span>] IToastNotificationService ToastService { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
<span class="hljs-function"><span class="hljs-keyword">protected</span> <span class="hljs-keyword">override</span> <span class="hljs-keyword">void</span> <span class="hljs-title">OnAfterRender</span>(<span class="hljs-params"><span class="hljs-built_in">bool</span> firstRender</span>)</span> {
ToastService.ShowToast(<span class="hljs-keyword">new</span> ToastOptions {
ProviderName = <span class="hljs-string">"ToastContainer"</span>,
Text = <span class="hljs-string">"The process has been completed."</span>
});
}
</span><span class="hljs-built_in">}</span></code></pre>
</div>
</div>
<p> In both instances, you must add the <a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxToastProvider?v=24.1" target="_blank" rel="noopener">DxToastProvider</a> component to a page. This component serves as a toast
container and should be declared where toasts will be displayed. </p>
<p><a href="https://demos.devexpress.com/blazor/Toast" target="_blank" rel="noopener" class="Button Gray">Online Demo</a></p> <span class="H-Separator"></span>
<h3 data-anchor="blazor-progressbar" data-toc-title="New Progress Bar">
<a name="blazor-progressbar" class="anchor"></a>New Progress Bar
</h3>
<p> The new DevExpress <a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxProgressBar?v=24.1" target="_blank" rel="noopener">Blazor Progress Bar</a> component allows you to communicate the status of ongoing processes with
end-users. When progress cannot be estimated, the component can display an infinite moving bar. The control includes the following integrated features: </p>
<ul>
<li>Horizontal, vertical, and circular layout</li>
<li>Four statuses to indicate process state: InProgress, Warning, Error, and Success</li>
<li>Indeterminate state</li>
<li>Element customization: icon, label, and bar thickness</li>
</ul>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-blazor-progress-bar.png" srcset="/subscriptions/i/24.1/24-1-blazor-progress-bar.png 1x, /subscriptions/i/24.1/24-1-blazor-progress-bar@2x.png 2x"
alt="Blazor Progress Bar, DevExpress" width="1054" height="240" style="border: none" id="ctl00_ctl00_Content_Content_ctl4219"></div>
<p><a href="https://demos.devexpress.com/blazor/ProgressBar" target="_blank" rel="noopener" class="Button Gray">Online Demo</a></p> <span class="H-Separator"></span>
<h3 data-anchor="blazor-bargauge" data-toc-title="New Bar Gauge">
<a name="blazor-bargauge" class="anchor"></a>New Bar Gauge
</h3>
<p> The <a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxBarGauge?v=24.1" target="_blank" rel="noopener">Bar Gauge</a> for Blazor allows you to display data as circular bars where each bar indicates a single value. The
component ships with the following capabilities: </p>
<ul>
<li>Geometry and layout configuration</li>
<li>Palette customization</li>
<li>Export and printing support</li>
<li>Real-time data updates</li>
<li>Gauge element customization: labels, tooltips, legend, and many more.</li>
</ul>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-blazor-bar-gauge.png" srcset="/subscriptions/i/24.1/24-1-blazor-bar-gauge.png 1x, /subscriptions/i/24.1/24-1-blazor-bar-gauge@2x.png 2x" alt="Blazor Bar Gauge, DevExpress"
width="476" height="510" style="border: none" id="ctl00_ctl00_Content_Content_ctl4234"></div>
<p><a href="https://demos.devexpress.com/blazor/BarGaugeGeometry" target="_blank" rel="noopener" class="Button Gray">Online Demo</a></p> <span class="H-Separator"></span>
<h3 data-anchor="blazor-sparkline" data-toc-title="New Sparkline">
<a name="blazor-sparkline" class="anchor"></a>New Sparkline
</h3>
<p> Our new <a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxSparkline?v=24.1" target="_blank" rel="noopener">Blazor Sparkline</a> component allows you to display value trends using a compact UI metaphor. You can use the
DevExpress Blazor Sparkline as a standalone component or embed it into other UI controls. Sparkline allows you to configure all series and point settings at the root component level. Sparkline applies corresponding settings based on the
<a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxSparkline.Type?v=24.1" target="_blank" rel="noopener">Type</a> property value (which defines series type). In addition to series and point settings, you can configure
tooltips and customize the component's container. </p>
<p> Sparkline includes built-in export and print capabilities. You can call the
<a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxSparkline.ExportToAsync(System.String-DevExpress.Blazor.DataExportFormat)?v=24.1" target="_blank" rel="noopener">ExportToAsync</a> method to export data to a file (PNG,
PDF, JPEG, or SVG) or call the <a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxSparkline.GetSvgMarkupAsync?v=24.1" target="_blank" rel="noopener">GetSvgMarkup</a> method to obtain the component's SVG markup. </p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-blazor-sparkline.png" srcset="/subscriptions/i/24.1/24-1-blazor-sparkline.png 1x, /subscriptions/i/24.1/24-1-blazor-sparkline@2x.png 2x" alt="Blazor Sparkline, DevExpress"
width="1030" height="177" style="border: none" id="ctl00_ctl00_Content_Content_ctl4259"></div>
<p><a href="https://demos.devexpress.com/blazor/ChartSparkline" target="_blank" rel="noopener" class="Button Gray">Online Demo</a></p> <span class="H-Separator"></span>
<h3 data-anchor="blazor-rendering-engine" data-toc-title="New Rendering Engine">
<a name="blazor-rendering-engine" class="anchor"></a>New Rendering Engine
</h3>
<p> The following DevExpress Blazor components now use our optimized rendering engine (instead of Bootstrap): </p>
<ul>
<li><a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxChart-1" target="_blank" rel="noopener">Charts</a></li>
<li><a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.RichEdit.DxRichEdit" target="_blank" rel="noopener">Rich Text Editor</a></li>
<li><a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxScheduler" target="_blank" rel="noopener">Scheduler</a></li>
<li><a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxPivotGrid" target="_blank" rel="noopener">Pivot Grid</a></li>
<li><a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxUpload?v=24.1" target="_blank" rel="noopener">Upload</a></li>
<li><a href="https://docs.devexpress.com/XtraReports/DevExpress.Blazor.Reporting.DxReportViewer" target="_blank" rel="noopener">Report Viewer</a></li>
</ul> <span class="H-Separator"></span>
<h3 data-anchor="blazor-keyboard-support" data-toc-title="Keyboard Support">
<a name="blazor-keyboard-support" class="anchor"></a>Keyboard Support
</h3>
<p> To address accessibility standards and improve user experiences for those with disabilities, v24.1 adds keyboard navigation support for the following Blazor UI components: </p>
<ul>
<li><a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxDateEdit-1?v=24.1#keyboard-navigation" target="_blank" rel="noopener">Date Edit</a></li>
<li><a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxTimeEdit-1?v=24.1#keyboard-navigation" target="_blank" rel="noopener">Time Edit</a></li>
<li><a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxTreeView?v=24.1#keyboard-navigation" target="_blank" rel="noopener">Tree View</a></li>
<li><a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxAccordion?v=24.1#keyboard-navigation" target="_blank" rel="noopener">Accordion</a></li>
<li><a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxComboBox-2?v=24.1#keyboard-navigation" target="_blank" rel="noopener">ComboBox</a></li>
<li><a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxListBox-2?v=24.1#keyboard-navigation" target="_blank" rel="noopener">List Box</a></li>
<li><a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxTagBox-2?v=24.1#keyboard-navigation" target="_blank" rel="noopener">TagBox</a></li>
<li><a href="https://docs.devexpress.com/Blazor/404966/components/rich-edit/keyboard-support?v=24.1" target="_blank" rel="noopener">Rich Text Editor</a></li>
<li><a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxUpload?v=24.1#keyboard-navigation" target="_blank" rel="noopener">Upload</a></li>
<li><a href="https://docs.devexpress.com/XtraReports/DevExpress.Blazor.Reporting.DxReportViewer" target="_blank" rel="noopener">Report Viewer</a></li>
</ul> <span class="H-Separator"></span>
<h3 data-anchor="blazor-project-templates" data-toc-title="Project Templates">
<a name="blazor-project-templates" class="anchor"></a>Project Templates
</h3>
<h4 anchor="blazor-project-templates-net8-auth">
<a name="blazor-project-templates-net8-auth" class="anchor visible-anchor" href="#blazor-project-templates-net8-auth">#</a>.NET 8 Authentication and Authorization
</h4>
<p> Our Blazor project templates for .NET 8 include an option to add ASP.NET Core Identity and Token-based Authentication to your projects. In addition to the necessary infrastructure, our templates generate an authentication interface
powered by DevExpress Blazor components. </p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-blazor-templategallery.png" srcset="/subscriptions/i/24.1/24-1-blazor-templategallery.png 1x, /subscriptions/i/24.1/24-1-blazor-templategallery@2x.png 2x"
alt=".NET 8 Authentication and Authorization - Blazor Project Templates, DevExpress" width="998" height="644" style="border: none" id="ctl00_ctl00_Content_Content_ctl4290"></div> <span class="H-Separator"></span>
<h3 data-anchor="blazor-grid" data-toc-title="Grid">
<a name="blazor-grid" class="anchor"></a>Grid
</h3>
<h4 anchor="blazor-grid-header-bands">
<a name="blazor-grid-header-bands" class="anchor visible-anchor" href="#blazor-grid-header-bands">#</a>Header Bands
</h4>
<p> The DevExpress Blazor Grid can now arrange its columns into logical groups called <a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxGridBandColumn?v=24.1" target="_blank" rel="noopener">bands</a>. Each band contains its
own header displayed above column headers. Columns without a band span the entire band region. The Grid also supports multi-level bands wherein a band can display other bands within it. </p>
<p><a href="https://docs.devexpress.com/Blazor/404479/components/grid/columns/columns?v=24.1#band-column-header-bands" target="_blank" rel="noopener">Documentation</a></p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-blazor-header-bands.png" srcset="/subscriptions/i/24.1/24-1-blazor-header-bands.png 1x, /subscriptions/i/24.1/24-1-blazor-header-bands@2x.png 2x"
alt="Header Bands - Blazor Grid, DevExpress" width="1044" height="400" style="border: none" id="ctl00_ctl00_Content_Content_ctl4308"></div>
<p> While end-users can reorder columns within bands or move them to the Group Panel, column movement between bands is restricted. </p>
<p> The Grid’s <a href="https://docs.devexpress.com/Blazor/404479/components/grid/columns/columns?v=24.1#column-chooser" target="_blank" rel="noopener">Column Chooser</a> has also been updated to support Header Bands. It displays bands
and columns hierarchically and allows end-users to toggle the visibility of entire groups, not just individual columns. </p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-blazor-column-chooser.png" srcset="/subscriptions/i/24.1/24-1-blazor-column-chooser.png 1x, /subscriptions/i/24.1/24-1-blazor-column-chooser@2x.png 2x"
alt="Column Chooser and Header Bands - Blazor Grid, DevExpress" width="788" height="432" style="border: none" id="ctl00_ctl00_Content_Content_ctl4316"></div>
<p><a href="https://demos.devexpress.com/blazor/Grid/Columns/HeaderBands" target="_blank" rel="noopener" class="Button Gray">Online Demo</a></p> <span class="H-Separator"></span>
<h4 anchor="blazor-grid-export-server-side-data">
<a name="blazor-grid-export-server-side-data" class="anchor visible-anchor" href="#blazor-grid-export-server-side-data">#</a>Export Server-Side Data
</h4>
<p> v24.1 introduces Blazor Grid data export functionality for any supported server-side data/Server Mode sources (<code data-renderer="hljs" class="csharp" data-control="Code-Inline">GridDevExtremeDataSource</code>, or <code
data-renderer="hljs" class="csharp" data-control="Code-Inline">CustomDataSource</code>). Remote data can be exported to XLS, XLSX, and CSV formats. </p>
<p> The DevExpress Blazor Grid can now fetch records from a remote data source to/from the exported document. While fetching records, the Grid displays a loading indicator. To avoid flickering, the indicator is displayed only during
estimated fetch time. For more information on this feature, refer to the following help topic: <a href="https://docs.devexpress.com/Blazor/404338/components/grid/export" target="_blank" rel="noopener">Data Export</a>. </p>
<p><a href="https://demos.devexpress.com/blazor/Grid/Export/LargeQueryable" target="_blank" rel="noopener" class="Button Gray">Online Demo</a></p> <span class="H-Separator"></span>
<h4 anchor="blazor-grid-cell-editor-appearance">
<a name="blazor-grid-cell-editor-appearance" class="anchor visible-anchor" href="#blazor-grid-cell-editor-appearance">#</a>New Cell Editor Appearance
</h4>
<p> In-place editors in the filter row, edit row, and edit cells of the DevExpress Blazor Grid ship with a new improved look/feel - and automatically display validation icons, when required. The appearance of grid cells is now consistent
in both display and edit modes. </p>
<p></p>
<div data-control="image-comparer" data-comparer-theme="dark" data-label-before="v23.2" data-label-after="v24.1" data-comparer-position="50" class="icv icv__icv--horizontal standard"><img
src="/subscriptions/i/24.1/24-1-blazor-cell-editor-appearance-slider-before.png"
srcset="/subscriptions/i/24.1/24-1-blazor-cell-editor-appearance-slider-before.png 1x, /subscriptions/i/24.1/24-1-blazor-cell-editor-appearance-slider-before@2x.png 2x" alt="Blazor Grid v23.2, DevExpress" width="1052" height="268"
style="border: none; width: 810px; height: 412.688px;" id="ctl00_ctl00_Content_Content_ctl5168" class="icv__img icv__img-a"><span class="icv__label icv__label-before keep">v23.2</span><span
class="icv__label icv__label-after keep">v24.1</span>
<div class="icv__wrapper" style="width: 50%; height: 50%; transition: all 100ms ease-out 0s;"><img src="/subscriptions/i/24.1/24-1-blazor-cell-editor-appearance-slider-after.png"
srcset="/subscriptions/i/24.1/24-1-blazor-cell-editor-appearance-slider-after.png 1x, /subscriptions/i/24.1/24-1-blazor-cell-editor-appearance-slider-after@2x.png 2x" alt="Blazor Grid v24.1, DevExpress" width="1052" height="268"
style="border: none; width: 810px; height: 412.688px;" id="ctl00_ctl00_Content_Content_ctl5169" class="icv__img icv__img-b"></div>
<div class="icv__control" style="width: 50px; left: calc(50% - 25px); transition: all 100ms ease-out 0s;">
<div class="icv__control-line" style="width: 2px; background: rgb(48, 48, 48); box-shadow: rgba(0, 0, 0, 0.33) 0px 0px 15px;"></div>
<div class="icv__theme-wrapper">
<div class="icv__arrow-wrapper" style="transform: translateX(8px);"><svg height="15" width="15" style="
transform:
scale(1.5)
rotateZ(180deg); height: 20px; width: 20px;
-webkit-filter: drop-shadow( 0px 3px 5px rgba(0, 0, 0, .33));
filter: drop-shadow( 0px -3px 5px rgba(0, 0, 0, .33));
" xmlns="http://www.w3.org/2000/svg" data-name="Layer 1" viewBox="0 0 15 15">
<path fill="#303030" stroke="#303030" stroke-linecap="round" stroke-width="0" d="M4.5 1.9L10 7.65l-5.5 5.4"></path>
</svg></div>
<div class="icv__arrow-wrapper" style="transform: translateX(-8px);"><svg height="15" width="15" style="
transform:
scale(1.5)
rotateZ(0deg); height: 20px; width: 20px;
-webkit-filter: drop-shadow( 0px 3px 5px rgba(0, 0, 0, .33));
filter: drop-shadow( 0px 3px 5px rgba(0, 0, 0, .33));
" xmlns="http://www.w3.org/2000/svg" data-name="Layer 1" viewBox="0 0 15 15">
<path fill="#303030" stroke="#303030" stroke-linecap="round" stroke-width="0" d="M4.5 1.9L10 7.65l-5.5 5.4"></path>
</svg></div>
</div>
<div class="icv__control-line" style="width: 2px; background: rgb(48, 48, 48); box-shadow: rgba(0, 0, 0, 0.33) 0px 0px 15px;"></div>
</div>
</div>
<p></p>
<p><a href="https://demos.devexpress.com/blazor/Grid/EditData/EditCell" target="_blank" rel="noopener" class="Button Gray">Online Demo</a></p> <span class="H-Separator"></span>
<h4 anchor="blazor-grid-editing">
<a name="blazor-grid-editing" class="anchor visible-anchor" href="#blazor-grid-editing">#</a>Cell Editing Enhancements
</h4>
<p> Our Blazor Grid's Edit Cell mode feature is now official and includes Virtual Scrolling support. It now ships with the following enhancements: </p>
<ul>
<li>Users can now change a check box value with a single click.</li>
<li>The Grid automatically selects cell text when the cell switches to edit mode.</li>
<li>The Grid now automatically updates the focused row when switching to edit mode.</li>
<li>The Grid’s new <a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxGrid.GetEditContext?v=24.1" target="_blank" rel="noopener">GetEditContext</a> method allows you to obtain edit context at any time.</li>
<li>Column text alignment affects editors displayed inside the column.</li>
</ul> <span class="H-Separator"></span>
<h4 anchor="blazor-grid-keyboard-nav">
<a name="blazor-grid-keyboard-nav" class="anchor visible-anchor" href="#blazor-grid-keyboard-nav">#</a>Keyboard Navigation Enhancements and New Tab Navigation
</h4>
<p> In v24.1, our Blazor Grid ships with enhanced <a href="https://docs.devexpress.com/Blazor/404652/components/grid/keyboard-support?v=24.1" target="_blank" rel="noopener">keyboard navigation</a> and virtual scrolling support. The Grid
component now automatically activates keyboard navigation and built-in shortcuts (<strong>Note</strong>: You may want to remove the <code data-renderer="hljs" class="csharp" data-control="Code-Inline">KeyboardNavigationEnabled</code>
property from your project as it's now obsolete). </p>
<p> The Tab key navigates between all Grid cells regardless of a cell editor's active state. Users can also leave the table area by pressing Ctrl + Up or Ctrl + Down (Alt + Up or Alt + Down on Mac). </p>
<p> In addition, we improved the <a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxGrid.RowClick?v=24.1" target="_blank" rel="noopener">RowClick</a> event. With v24.1, this event allows you to implement custom actions in
response to mouse clicks and after a user presses Enter when a data row has focus. </p> <span class="H-Separator"></span>
<h4 anchor="blazor-grid-value-posting">
<a name="blazor-grid-value-posting" class="anchor visible-anchor" href="#blazor-grid-value-posting">#</a>Built-in Value Posting
</h4>
<p> We added the following new method to <a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxGrid.EditModelSaving" target="_blank" rel="noopener">EditModelSaving</a> event arguments:
<a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.GridEditModelSavingEventArgs.CopyChangesToDataItem?v=24.1" target="_blank" rel="noopener">CopyChangesToDataItem</a>. This method allows you to copy all changes made to the
edit model during editing. Complex field values can be copied as well. </p>
<p> The following v23.2 code snippet... </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">C#</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="csharp"><span class="hljs-function"><span class="hljs-keyword">async</span> Task <span class="hljs-title">OnEditModelSaving</span>(<span class="hljs-params">GridEditModelSavingEventArgs e</span>)</span> {
<span class="hljs-keyword">var</span> editModel = (EmployeeEditModel)e.EditModel;
<span class="hljs-keyword">if</span> (dataItem != <span class="hljs-literal">null</span>) {
dataItem.FirstName = editModel.FirstName;
dataItem.LastName = editModel.LastName;
dataItem.Title = editModel.Title;
dataItem.HireDate = editModel.HireDate;
}
}</code></pre>
</div>
</div>
<p> ... can now be replaced with a shorter version: </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">C#</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="csharp"><span class="hljs-function"><span class="hljs-keyword">async</span> Task <span class="hljs-title">OnEditModelSaving</span>(<span class="hljs-params">GridEditModelSavingEventArgs e</span>)</span> {
<span class="hljs-keyword">var</span> editModel = (EmployeeEditModel)e.EditModel;
<span class="hljs-keyword">if</span> (dataItem != <span class="hljs-literal">null</span>) {
e.CopyChangesToDataItem();
}
}</code></pre>
</div>
</div> <span class="H-Separator"></span>
<h4 anchor="blazor-grid-dateonly-timeonly-support">
<a name="blazor-grid-dateonly-timeonly-support" class="anchor visible-anchor" href="#blazor-grid-dateonly-timeonly-support">#</a>DateOnly and TimeOnly Support
</h4>
<p> With v24.1, our Blazor Grid component supports <code data-renderer="hljs" class="csharp" data-control="Code-Inline">DateOnly</code> and <code data-renderer="hljs" class="csharp" data-control="Code-Inline">TimeOnly</code> types for the
following: </p>
<ul>
<li>Sorting</li>
<li>Filtering</li>
<li>Hierarchical Filter Menu for DateOnly values</li>
<li>Grouping</li>
<li>Summaries</li>
<li>Auto-generated cell editors</li>
<li>Interval grouping for DateOnly values</li>
<li>Value formatting using DisplayFormat</li>
<li>Excel Export</li>
</ul> <span class="H-Separator"></span>
<h4 anchor="blazor-grid-skeletons">
<a name="blazor-grid-skeletons" class="anchor visible-anchor" href="#blazor-grid-skeletons">#</a>Enable/Disable Skeletons
</h4>
<p> The DevExpress Blazor Grid no longer displays skeletons by default when Virtual Scrolling is used with local data. Since rows in a local data source are usually rendered quickly, this new behavior produces a more fluid experience,
with fewer visual updates. </p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-blazor-grid-no-skeletons.gif" alt="DevExpress Blazor Grid - Display Skeletons" width="963" height="425" style="border: none" id="ctl00_ctl00_Content_Content_ctl4426"></div>
<p> Skeletons are still enabled by default for remote data sources (for record loading from a server or database). You can now use the
<a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxGrid.SkeletonRowsEnabled?v=24.1" target="_blank" rel="noopener">SkeletonRowsEnabled</a> property to control skeleton behavior - enable it for local sources or disable it
for remote sources if server response time is acceptable. </p> <span class="H-Separator"></span>
<h4 anchor="blazor-grid-highlight-rows-on-hover">
<a name="blazor-grid-highlight-rows-on-hover" class="anchor visible-anchor" href="#blazor-grid-highlight-rows-on-hover">#</a>Highlight Rows on Hover
</h4>
<p> To highlight Blazor Grid rows when hovering rows, simply enable our new <a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxGrid.HighlightRowOnHover?v=24.1" target="_blank" rel="noopener">HighlightRowOnHover</a> property
(highlight color is based on the theme used within your DevExpress-powered Blazor app). </p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-blazor-grid-highlight-row-on-hover.png"
srcset="/subscriptions/i/24.1/24-1-blazor-grid-highlight-row-on-hover.png 1x, /subscriptions/i/24.1/24-1-blazor-grid-highlight-row-on-hover@2x.png 2x" alt="DevExpress Blazor Grid - Highlight Rows on Hover" width="1052" height="242"
style="border: none" id="ctl00_ctl00_Content_Content_ctl4443"></div> <span class="H-Separator"></span>
<h3 data-anchor="blazor-charts" data-toc-title="Charts">
<a name="blazor-charts" class="anchor"></a>Charts
</h3>
<h4 anchor="blazor-charts-">
<a name="blazor-charts-" class="anchor visible-anchor" href="#blazor-charts-">#</a>Annotations
</h4>
<p> The new Blazor <a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxChartAnnotationBase-1?v=24.1" target="_blank" rel="noopener">DxChartAnnotation</a> object allows you to create chart annotations — comments that contain
information about chart content. You can populate annotations with image or text content. You can also anchor annotations to chart elements (series points or axes) or position annotations based on pixel coordinates. DevExpress Blazor
Chart components also allow you to customize annotations as needed — you can configure annotation borders and shadows, image and text settings. </p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-blazor-chart-annotations.png" srcset="/subscriptions/i/24.1/24-1-blazor-chart-annotations.png 1x, /subscriptions/i/24.1/24-1-blazor-chart-annotations@2x.png 2x"
alt="Annotations - Blazor Charts, DevExpress" width="1040" height="352" style="border: none" id="ctl00_ctl00_Content_Content_ctl4458"></div>
<p><a href="https://demos.devexpress.com/blazor/ChartAnnotations" target="_blank" rel="noopener" class="Button Gray">Online Demo</a></p> <span class="H-Separator"></span>
<h4 anchor="blazor-charts-strips">
<a name="blazor-charts-strips" class="anchor visible-anchor" href="#blazor-charts-strips">#</a>Strips
</h4>
<p> Our new Blazor <a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxChartAxisStrip?v=24.1" target="_blank" rel="noopener">DxChartAxisStrip</a> object allows you to create and configure axis strips. You can use a strip to
highlight a range between two axis values or an area above/below a value. These highlighted areas help users determine whether a point falls in or out of a predefined range. You can also add a
<a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxChartAxisStripLabel?v=24.1" target="_blank" rel="noopener">DxChartAxisStripLabel</a> object to strip markup to display and configure strip labels. </p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-blazor-chart-strips.png" srcset="/subscriptions/i/24.1/24-1-blazor-chart-strips.png 1x, /subscriptions/i/24.1/24-1-blazor-chart-strips@2x.png 2x"
alt="Strips - Blazor Charts, DevExpress" width="1040" height="328" style="border: none" id="ctl00_ctl00_Content_Content_ctl4476"></div>
<p><a href="https://demos.devexpress.com/blazor/ChartAxesStrips" target="_blank" rel="noopener" class="Button Gray">Online Demo</a></p> <span class="H-Separator"></span>
<h4 anchor="blazor-charts-error-bars">
<a name="blazor-charts-error-bars" class="anchor visible-anchor" href="#blazor-charts-error-bars">#</a>Error Bars
</h4>
<p> The new <a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxChartSeriesValueErrorBar?v=24.1" target="_blank" rel="noopener">DxChartSeriesValueErrorBar</a> object allows you to configure error bars (indicate measurement
precision or uncertainty). They display a possible value range next to a series point. Error bars can display fixed values or percentages, statistical function values, or error values obtained from data source fields. </p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-blazor-chart-error-bar.png" srcset="/subscriptions/i/24.1/24-1-blazor-chart-error-bar.png 1x, /subscriptions/i/24.1/24-1-blazor-chart-error-bar@2x.png 2x"
alt="Error Bars - Blazor Charts, DevExpress" width="1040" height="476" style="border: none" id="ctl00_ctl00_Content_Content_ctl4491"></div>
<p><a href="https://demos.devexpress.com/blazor/ChartErrorBars" target="_blank" rel="noopener" class="Button Gray">Online Demo</a></p> <span class="H-Separator"></span>
<h4 anchor="blazor-charts-tooltips">
<a name="blazor-charts-tooltips" class="anchor visible-anchor" href="#blazor-charts-tooltips">#</a>Tooltip Enhancements
</h4>
<p> v24.1 introduces extended tooltip functionality for DevExpress Blazor Chart components. You can now change tooltip visibility for individual series points in code. To display a tooltip for a particular series point, call
component-specific ShowTooltip method overloads (<a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxChart-1.ShowTooltip.overloads?v=24.1" target="_blank" rel="noopener">DxChart.ShowTooltip</a>,
<a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxPieChart-1.ShowTooltip.overloads?v=24.1" target="_blank" rel="noopener">DxPieChart.ShowTooltip</a>, or
<a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxPolarChart-1.ShowTooltip.overloads?v=24.1" target="_blank" rel="noopener">DxPolarChart.ShowTooltip</a>). To hide the tooltip, call the
<a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxChartBase.HideTooltip?v=24.1" target="_blank" rel="noopener">HideTooltip</a> method. </p>
<p> With v24.1, you can also handle the <a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxChartBase.TooltipShowing?v=24.1" target="_blank" rel="noopener">TooltipShowing</a> event to obtain information about a tooltip before
it appears (or cancel the tooltip as needed). </p> <span class="H-Separator"></span>
<h4 anchor="blazor-charts-label-customization">
<a name="blazor-charts-label-customization" class="anchor visible-anchor" href="#blazor-charts-label-customization">#</a>Label Customization Enhancements
</h4>
<p> We expanded the list of available label customization settings. You can now set individual text for each point label using the
<a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.IChartSeriesLabel.Texts?v=24.1" target="_blank" rel="noopener">Texts</a> property. Moreover, you can modify the following properties for point labels: </p>
<ul>
<li><a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.IChartSeriesLabel.Alignment?v=24.1" target="_blank" rel="noopener">Alignment</a></li>
<li><a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.IChartSeriesLabel.HorizontalOffset?v=24.1" target="_blank" rel="noopener">HorizontalOffset</a></li>
<li><a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.IChartSeriesLabel.VerticalOffset?v=24.1" target="_blank" rel="noopener">VerticalOffset</a></li>
<li><a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.IChartSeriesLabel.RotationAngle?v=24.1" target="_blank" rel="noopener">RotationAngle</a></li>
<li><a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.IChartSeriesLabel.ShowForZeroValues?v=24.1" target="_blank" rel="noopener">ShowForZeroValues</a></li>
<li><a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.IChartSeriesLabel.Font?v=24.1" target="_blank" rel="noopener">Font</a></li>
<li><a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.IChartSeriesLabel.Border?v=24.1" target="_blank" rel="noopener">Border</a></li>
</ul> <span class="H-Separator"></span>
<h4 anchor="blazor-charts-live-updates">
<a name="blazor-charts-live-updates" class="anchor visible-anchor" href="#blazor-charts-live-updates">#</a>Live Update Enhancements
</h4>
<p> We extended our Blazor Chart’s live update capabilities and introduced <a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxChartAxisRange.Length?v=24.1" target="_blank" rel="noopener">Length</a> and
<a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.ChartVisualRangeUpdateMode?v=24.1">VisualRangeUpdateMode</a> properties. These enhancements allow the chart to retain its visual state (zoom and scroll position) when Chart
data changes. </p>
<p><a href="https://demos.devexpress.com/blazor/ChartRealTimeData" target="_blank" rel="noopener" class="Button Gray">Online Demo</a></p> <span class="H-Separator"></span>
<h4 anchor="blazor-charts-api">
<a name="blazor-charts-api" class="anchor visible-anchor" href="#blazor-charts-api">#</a>API Enhancements
</h4>
<p><strong>PieChart settings</strong>: </p>
<ul>
<li><a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxPieChart-1.SegmentDirection?v=24.1" target="_blank" rel="noopener">SegmentDirection</a> - Specifies the direction in which the chart arranges series slices.</li>
<li><a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxPieChart-1.StartAngle?v=24.1" target="_blank" rel="noopener">StartAngle</a> - Specifies the angle at which the chart positions the first series slice.</li>
</ul>
<p><strong>Axis settings</strong>: </p>
<ul>
<li><a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxChartArgumentAxis.WorkdaysOnly?v=24.1" target="_blank" rel="noopener">WorkdaysOnly</a> - Specifies whether the chart displays only workdays on the axis.</li>
<li><a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxChartArgumentAxis.WorkWeek?v=24.1" target="_blank" rel="noopener">WorkWeek</a> - Specifies weekdays DxChart treats as workdays.</li>
<li><a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxChartArgumentAxis.WorkDates?v=24.1" target="_blank" rel="noopener">WorkDates</a> - Specifies dates DxChart treats as workdays.</li>
<li><a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxChartArgumentAxis.Holidays?v=24.1" target="_blank" rel="noopener">Holidays</a> - Specifies dates DxChart marks as holidays.</li>
</ul>
<p><strong>Axis Range settings</strong>: </p>
<ul>
<li><a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxChartAxisRange.Length?v=24.1" target="_blank" rel="noopener">Length</a> - Specifies range length.</li>
<li><a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxChartAxis-1.MinVisualRangeLength?v=24.1" target="_blank" rel="noopener">MinVisualRangeLength</a> - Specifies the minimum length of the visual range.</li>
<li><a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxChartAxis-1.VisualRangeUpdateMode?v=24.1" target="_blank" rel="noopener">VisualRangeUpdateMode</a> - Specifies how the visual range behaves if new points are added to
the data source.</li>
</ul> <span class="H-Separator"></span>
<h3 data-anchor="blazor-combobox-tagbox" data-toc-title="New ComboBox and TagBox">
<a name="blazor-combobox-tagbox" class="anchor"></a>New ComboBox and TagBox
</h3>
<p> We've rebuilt the DevExpress Blazor <a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxComboBox-2?v=24.1" target="_blank" rel="noopener">ComboBox</a> and
<a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxTagBox-2?v=24.1" target="_blank" rel="noopener">TagBox</a> components, maintaining their existing API while revamping visual and data layers for improved stability,
visuals, and performance. These changes form the basis for upcoming features and enhancements, with many already available in v24.1. </p>
<p>
<a href="https://demos.devexpress.com/blazor/ComboBox" target="_blank" rel="noopener" class="Button Gray">Online Demo: ComboBox</a><a href="https://demos.devexpress.com/blazor/TagBox" target="_blank" rel="noopener" class="Button Gray">Online Demo: TagBox</a>
</p> <span class="H-Separator"></span>
<h4 anchor="blazor-combobox-tagbox-performance">
<a name="blazor-combobox-tagbox-performance" class="anchor visible-anchor" href="#blazor-combobox-tagbox-performance">#</a>Performance Enhancements
</h4>
<p> Overall ComboBox and TagBox performance has been improved significantly. Tasks like opening the dropdown, searching, or navigating through items are now more responsive. In addition, startup times for ComboBox/TagBox have been reduced
by up to three times. This boosts overall performance for forms that contain these editors and any components utilizing ComboBox/TagBox internally, such as our Blazor Grid, Rich Text Editor, Scheduler, and Toolbar. </p> <span
class="H-Separator"></span>
<h4 anchor="blazor-combobox-tagbox-multi-column-search">
<a name="blazor-combobox-tagbox-multi-column-search" class="anchor visible-anchor" href="#blazor-combobox-tagbox-multi-column-search">#</a>Search Across Multiple Columns
</h4>
<p> Based on customer feedback, our ComboBox and TagBox can now search for text in any defined column, even columns whose values are not displayed in the edit box. </p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-blazor-combobox-search-across-multiple-columns.png"
srcset="/subscriptions/i/24.1/24-1-blazor-combobox-search-across-multiple-columns.png 1x, /subscriptions/i/24.1/24-1-blazor-combobox-search-across-multiple-columns@2x.png 2x"
alt="Search Across Multiple Columns - Blazor ComboBox and TagBox, DevExpress" width="526" height="174" style="border: none" id="ctl00_ctl00_Content_Content_ctl4604"></div>
<p> Use the new <a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxListEditorColumn.SearchEnabled?v=24.1" target="_blank" rel="noopener">SearchEnabled</a> property to exclude specific columns from search when necessary. </p>
<span class="H-Separator"></span>
<h4 anchor="blazor-combobox-tagbox-search-api">
<a name="blazor-combobox-tagbox-search-api" class="anchor visible-anchor" href="#blazor-combobox-tagbox-search-api">#</a>New Search API
</h4>
<p> In addition to `Contains` and `StartsWith`, ComboBox and TagBox include an `Equals` condition for searching within collections of similarly named items. The new
<a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.Base.DxDropDownListEditorBase-2.SearchTextParseMode?v=24.1" target="_blank" rel="noopener">SearchTextParseMode</a> property also defines how editors interpret search strings
divided by spaces: </p>
<ul>
<li><code data-renderer="hljs" class="csharp" data-control="Code-Inline">GroupWordsByAnd</code> – search words are treated as individual conditions grouped by the AND logical operator; only items that match all of the words are
displayed.</li>
<li><code data-renderer="hljs" class="csharp" data-control="Code-Inline">GroupWordsByOr</code> – search words are treated as individual conditions grouped by the OR logical operator; items that match at least one of these words are
displayed.</li>
<li><code data-renderer="hljs" class="csharp" data-control="Code-Inline">ExactMatch</code> – search words are not treated separately; only items that match search text (exact match) are displayed.</li>
</ul> <span class="H-Separator"></span>
<h4 anchor="blazor-combobox-tagbox-templates">
<a name="blazor-combobox-tagbox-templates" class="anchor visible-anchor" href="#blazor-combobox-tagbox-templates">#</a>New Templates
</h4>
<p> We've introduced new templates for ComboBox and TagBox to simplify popular customization usage scenarios: </p>
<ul>
<li><a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxComboBox-2.ColumnCellDisplayTemplate?v=24.1" target="_blank" rel="noopener">ColumnCellDisplayTemplate</a> – allows you to implement custom formatting for values in a
multi-column ComboBox/TagBox.</li>
<li>
<a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxComboBox-2.ItemDisplayTemplate?v=24.1" target="_blank" rel="noopener">ItemDisplayTemplate</a>/<a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxTagBox-2.TagDisplayTemplate?v=24.1" target="_blank" rel="noopener">TagDisplayTemplate</a>
– these templates are similar to <code data-renderer="hljs" class="csharp" data-control="Code-Inline">ItemTemplate</code>/<code data-renderer="hljs" class="csharp" data-control="Code-Inline">TagTemplate</code> (available previously),
but offer information about the underlying data item, value, and displayed text in context.</li>
<li><a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxComboBox-2.EmptyDataAreaTemplate?v=24.1" target="_blank" rel="noopener">EmptyDataAreaTemplate</a> – allows you to customize the area displayed when the ComboBox/TagBox
popup displays no items.</li>
</ul> <span class="H-Separator"></span>
<h4 anchor="blazor-combobox-tagbox-keyboard-nav">
<a name="blazor-combobox-tagbox-keyboard-nav" class="anchor visible-anchor" href="#blazor-combobox-tagbox-keyboard-nav">#</a>Keyboard Navigation Enhancements
</h4>
<p> Both ComboBox and TagBox now use a client-side keyboard navigation engine in their dropdowns. This makes keyboard navigation more responsive in Blazor Server apps since each keystroke doesn’t need to be sent to the server. In
addition, keyboard navigation is now more stable when used in combination with Virtual Scrolling. </p> <span class="H-Separator"></span>
<h3 data-anchor="blazor-listbox" data-toc-title="List Box">
<a name="blazor-listbox" class="anchor"></a>List Box
</h3>
<h4 anchor="blazor-listbox-">
<a name="blazor-listbox-" class="anchor visible-anchor" href="#blazor-listbox-">#</a>New Search and Filter API
</h4>
<p> The DevExpress Blazor List Box introduces new API that allows you to connect it to external search/filter UI elements: </p>
<ul>
<li><a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxListBox-2.SearchText?v=24.1" target="_blank" rel="noopener">SearchText</a> – specifies text used by the List Box to filter and highlight search results.</li>
<li><a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxListBox-2.SearchTextParseMode?v=24.1" target="_blank" rel="noopener">SearchTextParseMode</a> – specifies how the List Box interprets search strings divided by spaces.
</li>
<li>
<a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxListBox-2.SetFilterCriteria(DevExpress.Data.Filtering.CriteriaOperator)?v=24.1" target="_blank" rel="noopener">SetFilterCriteria</a>/<a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxListBox-2.GetFilterCriteria?v=24.1" target="_blank" rel="noopener">GetFilterCriteria</a>/<a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxListBox-2.ClearFilter?v=24.1" target="_blank" rel="noopener">ClearFilter</a>
– allows you to apply filters (of any complexity) using the CriteriaOperator language.</li>
</ul>
<p><a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxListBox-2?v=24.1#search-and-filter" target="_blank" rel="noopener">Documentation</a></p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-blazor-listbox-new-search-api.png" srcset="/subscriptions/i/24.1/24-1-blazor-listbox-new-search-api.png 1x, /subscriptions/i/24.1/24-1-blazor-listbox-new-search-api@2x.png 2x"
alt="Blazor List Box, DevExpress" width="690" height="308" style="border: none" id="ctl00_ctl00_Content_Content_ctl4654"></div>
<p><a href="https://demos.devexpress.com/blazor/ListBox#SearchText" target="_blank" rel="noopener" class="Button Gray">Online Demo</a></p> <span class="H-Separator"></span>
<h4 anchor="blazor-listbox-scroll-api">
<a name="blazor-listbox-scroll-api" class="anchor visible-anchor" href="#blazor-listbox-scroll-api">#</a>New Scroll API
</h4>
<p> The following new APIs allow you to scroll to a specific ListBox item: </p>
<ul>
<li><a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxListBox-2.MakeItemVisible(System.Int32)?v=24.1" target="_blank" rel="noopener">MakeItemVisible</a> – scrolls to an item with a specified visible index.</li>
<li><a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxListBox-2.MakeDataItemVisibleAsync(-0)?v=24.1" target="_blank" rel="noopener">MakeDataItemVisibleAsync</a> – finds a data item in the list and scrolls to it.</li>
</ul> <span class="H-Separator"></span>
<h3 data-anchor="blazor-datetime-editors" data-toc-title="Date Edit & Time Edit">
<a name="blazor-datetime-editors" class="anchor"></a>Date Edit & Time Edit
</h3>
<h4 anchor="blazor-datetime-editors-dateonly-timeonly-support">
<a name="blazor-datetime-editors-dateonly-timeonly-support" class="anchor visible-anchor" href="#blazor-datetime-editors-dateonly-timeonly-support">#</a>DateOnly and TimeOnly Support
</h4>
<p> DevExpress Blazor <a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxDateEdit-1?v=24.1" target="_blank" rel="noopener">Date Edit</a> and
<a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxTimeEdit-1?v=24.1" target="_blank" rel="noopener">Time Edit</a> components now support <code data-renderer="hljs" class="csharp" data-control="Code-Inline">DateOnly</code>
and <code data-renderer="hljs" class="csharp" data-control="Code-Inline">TimeOnly</code> values, respectively. All editor features - including masks, formatting API, and validation - now function properly with these new data types. </p>
<span class="H-Separator"></span>
<h3 data-anchor="blazor-file-management" data-toc-title="File Management">
<a name="blazor-file-management" class="anchor"></a>File Management
</h3>
<h4 anchor="blazor-upload-appearance">
<a name="blazor-upload-appearance" class="anchor visible-anchor" href="#blazor-upload-appearance">#</a>New Upload Appearance
</h4>
<p> Our Blazor Upload component's file list ships with a revamped look and feel. To make the list more understandable and visually compact, we removed the common progress bar, resized and rearranged UI elements, updated icons, and added
text to certain action buttons. </p>
<p></p>
<div data-control="image-comparer" data-comparer-theme="dark" data-label-before="v23.2" data-label-after="v24.1" data-comparer-position="50" class="icv icv__icv--horizontal standard"><img
src="/subscriptions/i/24.1/24-1-blazor-fm-uploader-appearance-1.png" srcset="/subscriptions/i/24.1/24-1-blazor-fm-uploader-appearance-1.png 1x, /subscriptions/i/24.1/24-1-blazor-fm-uploader-appearance-1@2x.png 2x"
alt="Blazor Upload v 23.2, DevExpress" width="1078" height="372" style="border: none; width: 810px; height: 559.031px;" id="ctl00_ctl00_Content_Content_ctl5354" class="icv__img icv__img-a"><span
class="icv__label icv__label-before keep">v23.2</span><span class="icv__label icv__label-after keep">v24.1</span>
<div class="icv__wrapper" style="width: 50%; height: 50%; transition: all 100ms ease-out 0s;"><img src="/subscriptions/i/24.1/24-1-blazor-fm-uploader-appearance-2.png"
srcset="/subscriptions/i/24.1/24-1-blazor-fm-uploader-appearance-2.png 1x, /subscriptions/i/24.1/24-1-blazor-fm-uploader-appearance-2@2x.png 2x" alt="Blazor Upload v24.1, DevExpress" width="1078" height="372"
style="border: none; width: 810px; height: 559.031px;" id="ctl00_ctl00_Content_Content_ctl5355" class="icv__img icv__img-b"></div>
<div class="icv__control" style="width: 50px; left: calc(50% - 25px); transition: all 100ms ease-out 0s;">
<div class="icv__control-line" style="width: 2px; background: rgb(48, 48, 48); box-shadow: rgba(0, 0, 0, 0.33) 0px 0px 15px;"></div>
<div class="icv__theme-wrapper">
<div class="icv__arrow-wrapper" style="transform: translateX(8px);"><svg height="15" width="15" style="
transform:
scale(1.5)
rotateZ(180deg); height: 20px; width: 20px;
-webkit-filter: drop-shadow( 0px 3px 5px rgba(0, 0, 0, .33));
filter: drop-shadow( 0px -3px 5px rgba(0, 0, 0, .33));
" xmlns="http://www.w3.org/2000/svg" data-name="Layer 1" viewBox="0 0 15 15">
<path fill="#303030" stroke="#303030" stroke-linecap="round" stroke-width="0" d="M4.5 1.9L10 7.65l-5.5 5.4"></path>
</svg></div>
<div class="icv__arrow-wrapper" style="transform: translateX(-8px);"><svg height="15" width="15" style="
transform:
scale(1.5)
rotateZ(0deg); height: 20px; width: 20px;
-webkit-filter: drop-shadow( 0px 3px 5px rgba(0, 0, 0, .33));
filter: drop-shadow( 0px 3px 5px rgba(0, 0, 0, .33));
" xmlns="http://www.w3.org/2000/svg" data-name="Layer 1" viewBox="0 0 15 15">
<path fill="#303030" stroke="#303030" stroke-linecap="round" stroke-width="0" d="M4.5 1.9L10 7.65l-5.5 5.4"></path>
</svg></div>
</div>
<div class="icv__control-line" style="width: 2px; background: rgb(48, 48, 48); box-shadow: rgba(0, 0, 0, 0.33) 0px 0px 15px;"></div>
</div>
</div>
<p></p>
<p><a href="https://demos.devexpress.com/blazor/Upload" target="_blank" rel="noopener" class="Button Gray">Online Demo</a></p> <span class="H-Separator"></span>
<h3 data-anchor="blazor-form-layout" data-toc-title="Form Layout">
<a name="blazor-form-layout" class="anchor"></a>Form Layout
</h3>
<h4 anchor="blazor-form-layout-item-caption-template">
<a name="blazor-form-layout-item-caption-template" class="anchor visible-anchor" href="#blazor-form-layout-item-caption-template">#</a>Item Caption Template
</h4>
<p> The new <a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxFormLayoutItem.CaptionTemplate?v=24.1" target="_blank" rel="noopener">DxFormLayoutItem.CaptionTemplate</a> property allows you to set icons, buttons, links, or
other elements near each <code data-renderer="hljs" class="csharp" data-control="Code-Inline">LayoutItem</code> caption. </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">Razor</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="razor"><span class="hljs-tag"><<span class="hljs-name">DxFormLayoutItem</span>></span>
<span class="hljs-tag"><<span class="hljs-name">CaptionTemplate</span>></span>
<span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"email-caption"</span>></span>
<span class="hljs-tag"><<span class="hljs-name">label</span> <span class="hljs-attr">for</span>=<span class="hljs-string">"contactEmail"</span>></span>Email<span class="hljs-tag"></<span class="hljs-name">label</span>></span>
<span class="hljs-tag"><<span class="hljs-name">DxButton</span> <span class="hljs-attr">CssClass</span>=<span class="hljs-string">"info-icon-btn"</span>
<span class="hljs-attr">IconCssClass</span>=<span class="hljs-string">"info-icon text-info"</span>
<span class="hljs-attr">RenderStyle</span>=<span class="hljs-string">"<span class="hljs-built_in">@</span><span class="language-csharp">ButtonRenderStyle.None</span>"</span>
<span class="hljs-attr">Click</span>=<span class="hljs-string">"() => IsInfoOpen = !IsInfoOpen"</span> /></span>
<span class="hljs-tag"><<span class="hljs-name">DxFlyout</span> @<span class="hljs-attr">bind-IsOpen</span>=<span class="hljs-string">@IsInfoOpen</span>
<span class="hljs-attr">PositionTarget</span>=<span class="hljs-string">".info-icon-btn"</span>
<span class="hljs-attr">PreventCloseOnPositionTargetClick</span>=<span class="hljs-string">"true"</span>
<span class="hljs-attr">Width</span>=<span class="hljs-string">"240"</span>></span>
Email must contain the company's domain name.
<span class="hljs-tag"></<span class="hljs-name">DxFlyout</span>></span>
<span class="hljs-tag"></<span class="hljs-name">div</span>></span>
<span class="hljs-tag"></<span class="hljs-name">CaptionTemplate</span>></span>
<span class="hljs-tag"><<span class="hljs-name">Template</span>></span>
<span class="hljs-tag"><<span class="hljs-name">DxTextBox</span> @<span class="hljs-attr">bind-Text</span>=<span class="hljs-string">"<span class="hljs-built_in">@</span><span class="language-csharp">Email</span>"</span> <span class="hljs-attr">InputId</span>=<span class="hljs-string">"contactEmail"</span><span class="hljs-string">/</span>></span>
<span class="hljs-tag"></<span class="hljs-name">Template</span>></span>
<span class="hljs-tag"></<span class="hljs-name">DxFormLayoutItem</span>></span></code></pre>
</div>
</div>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-blazor-form-layout.png" srcset="/subscriptions/i/24.1/24-1-blazor-form-layout.png 1x, /subscriptions/i/24.1/24-1-blazor-form-layout@2x.png 2x"
alt="Item Caption Template - Blazor Form Layout, DevExpress" width="914" height="172" style="border: none" id="ctl00_ctl00_Content_Content_ctl4721"></div>
<p><a href="https://demos.devexpress.com/blazor/FormLayout#Overview" target="_blank" rel="noopener" class="Button Gray">Online Demo</a></p> <span class="H-Separator"></span>
<h3 data-anchor="blazor-richtexteditor" data-toc-title="Rich Text Editor">
<a name="blazor-richtexteditor" class="anchor"></a>Rich Text Editor
</h3>
<h4 anchor="blazor-richtexteditor-table-api">
<a name="blazor-richtexteditor-table-api" class="anchor visible-anchor" href="#blazor-richtexteditor-table-api">#</a>New Table API
</h4>
<p> With v24.1, the DevExpress Rich Text Editor for Blazor allows you to modify table layout, decoration, and structure at runtime. </p>
<p><a href="https://docs.devexpress.com/Blazor/404904/components/rich-edit/examples/tables?v=24.1" target="_blank" rel="noopener">Documentation</a></p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">Razor</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="razor"><span class="hljs-tag"><<span class="hljs-name">DxRichEdit</span> @<span class="hljs-attr">ref</span>=<span class="hljs-string">"<span class="hljs-built_in">@</span><span class="language-csharp">richEdit</span>"</span> /></span>
<span class="hljs-built_in">@code {</span><span class="language-csharp">
DxRichEdit richEdit { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
</span><span class="hljs-comment">@* ... *@</span><span class="language-csharp">
<span class="hljs-keyword">try</span> {
@* ... *@
<span class="hljs-keyword">var</span> columnCount = <span class="hljs-number">4</span>;
<span class="hljs-keyword">var</span> rowCount = <span class="hljs-number">5</span>;
richEdit.DocumentAPI.BeginUpdate();
<span class="hljs-keyword">await</span> richEdit.DocumentAPI.Tables.CreateAsync(<span class="hljs-number">0</span>, columnCount, rowCount);
<span class="hljs-keyword">for</span> (<span class="hljs-built_in">int</span> i = <span class="hljs-number">0</span>; i < rowCount; i++)
<span class="hljs-keyword">for</span> (<span class="hljs-built_in">int</span> j = <span class="hljs-number">0</span>; j < columnCount; j++) {
<span class="hljs-keyword">var</span> myTable = <span class="hljs-keyword">await</span> richEdit.DocumentAPI.Tables.GetAsync(<span class="hljs-number">0</span>);
<span class="hljs-keyword">var</span> cellPosition = myTable.Rows[i].Cells[j].Interval.Start;
<span class="hljs-keyword">await</span> richEdit.DocumentAPI.AddTextAsync(cellPosition, <span class="hljs-string">"Row="</span> + (i + <span class="hljs-number">1</span>) + <span class="hljs-string">",Column="</span> + (j + <span class="hljs-number">1</span>));
}
richEdit.DocumentAPI.EndUpdate();
@* ... *@
}
<span class="hljs-keyword">catch</span> (OperationCanceledException e) {
@* ... *@
}
</span><span class="hljs-built_in">}</span></code></pre>
</div>
</div> <span class="H-Separator"></span>
<h4 anchor="blazor-richtexteditor-html-export-import">
<a name="blazor-richtexteditor-html-export-import" class="anchor visible-anchor" href="#blazor-richtexteditor-html-export-import">#</a>HTML Export/Import
</h4>
<p> The DevExpress Rich Text Editor for Blazor now supports document import/export in HTML format. You can add HTML markup to the main sub-document
(<a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.RichEdit.SubDocument.AddHtmlAsync.overloads?v=24.1" target="_blank" rel="noopener">AddHtmlAsync</a> method overloads), obtain HTML text and markup of the main sub-document
(<a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.RichEdit.SubDocument.GetHtmlAsync.overloads?v=24.1" target="_blank" rel="noopener">GetHtmlAsync</a> method overloads), and download document content to a file in HTML
format. </p>
<p><a href="https://demos.devexpress.com/blazor/RichEdit" target="_blank" rel="noopener" class="Button Gray">Online Demo</a></p> <span class="H-Separator"></span>
<h4 anchor="blazor-richtexteditor-context-menu">
<a name="blazor-richtexteditor-context-menu" class="anchor visible-anchor" href="#blazor-richtexteditor-context-menu">#</a>Context Menu Customization
</h4>
<p> v24.1 introduces extended UI customization options for the DevExpress Blazor Rich Text Editor. You can now customize the component's context menu and associated sub-menus. Handle the
<a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.RichEdit.DxRichEdit.CustomizeContextMenu?v=24.1" target="_blank" rel="noopener">CustomizeContextMenu</a> event to: </p>
<ul>
<li>Add or remove built-in menu items</li>
<li>Add custom menu items</li>
<li>Customize item appearance/behavior.</li>
</ul>
<p> With v24.1, you can also control context menu visibility using the <a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.RichEdit.DxRichEdit.ContextMenuEnabled?v=24.1" target="_blank" rel="noopener">ContextMenuEnabled</a>
property. </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">Razor</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="razor"><span class="hljs-tag"><<span class="hljs-name">DxRichEdit</span> <span class="hljs-attr">CustomizeContextMenu</span>=<span class="hljs-string">OnCustomizeContextMenu</span> /></span>
<span class="hljs-built_in">@code {</span><span class="language-csharp">
<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">OnCustomizeContextMenu</span>(<span class="hljs-params">IContextMenuItemCollection items</span>)</span> {
<span class="hljs-keyword">if</span> (selection.Intervals[<span class="hljs-number">0</span>].Length > <span class="hljs-number">0</span>) {
<span class="hljs-keyword">var</span> span = <span class="hljs-keyword">await</span> selection.ActiveSubDocument.GetTextSpanAsync(selection.Intervals[<span class="hljs-number">0</span>]);
textToSearch = span.Text.Trim();
}
<span class="hljs-keyword">else</span>
textToSearch = <span class="hljs-literal">null</span>;
<span class="hljs-keyword">var</span> searchItem = items.AddCustomItem(<span class="hljs-number">0</span>, <span class="hljs-string">"Google Search..."</span>, <span class="hljs-keyword">async</span> () => {
<span class="hljs-keyword">var</span> url = String.Format(<span class="hljs-string">"https://www.google.com/search?q={0}"</span>, HttpUtility.UrlEncode(textToSearch));
<span class="hljs-keyword">await</span> JSRuntime.InvokeVoidAsync(<span class="hljs-string">"open"</span>, url, <span class="hljs-string">"_blank"</span>);
});
searchItem.Enabled = !<span class="hljs-built_in">string</span>.IsNullOrEmpty(textToSearch);
searchItem.IconCssClass = <span class="hljs-string">"search-icon"</span>;
items.Remove(RichEditContextMenuItemNames.CutSelection);
items.Remove(RichEditContextMenuItemNames.CopySelection);
items.Remove(RichEditContextMenuItemNames.Paste);
<span class="hljs-keyword">var</span> clipboardItem = items.AddCustomItem(<span class="hljs-number">1</span>, <span class="hljs-string">"Clipboard"</span>);
clipboardItem.BeginGroup = <span class="hljs-literal">true</span>;
clipboardItem.Items.Add(RichEditContextMenuItemNames.CutSelection);
clipboardItem.Items.Add(RichEditContextMenuItemNames.CopySelection);
clipboardItem.Items.Add(RichEditContextMenuItemNames.Paste);
}
</span><span class="hljs-built_in">}</span></code></pre>
</div>
</div> <span class="H-Separator"></span>
<h3 data-anchor="blazor-scheduler" data-toc-title="Scheduler">
<a name="blazor-scheduler" class="anchor"></a>Scheduler
</h3>
<h4 anchor="blazor-scheduler-resources">
<a name="blazor-scheduler-resources" class="anchor visible-anchor" href="#blazor-scheduler-resources">#</a>Multiple Resources
</h4>
<p> Our Blazor Scheduler allows users to assign <a href="https://docs.devexpress.com/Blazor/404769/components/scheduler/resources#multiple-resources" target="_blank" rel="noopener">multiple resources</a> to an appointment. With v24,1,
users can create meetings with multiple participants, group events, or services that require coordination among multiple resources. To enable this functionality, use the
<a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxSchedulerDataStorage.EnableMultipleResources" target="_blank" rel="noopener">EnableMultipleResources</a> property. Once enabled, appointment forms will allow multiple
selection in the Resource field: </p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-blazor-scheduler-multiple-resources.png"
srcset="/subscriptions/i/24.1/24-1-blazor-scheduler-multiple-resources.png 1x, /subscriptions/i/24.1/24-1-blazor-scheduler-multiple-resources@2x.png 2x" alt="Multiple Resources - Blazor Scheduler, DevExpress" width="488" height="137"
style="border: none" id="ctl00_ctl00_Content_Content_ctl4792"></div>
<p> All selected resources will be displayed in the appointment tooltip: </p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-blazor-scheduler-multiple-resources-2.png"
srcset="/subscriptions/i/24.1/24-1-blazor-scheduler-multiple-resources-2.png 1x, /subscriptions/i/24.1/24-1-blazor-scheduler-multiple-resources-2@2x.png 2x" alt="Appointment Tooltip - Blazor Scheduler, DevExpress" width="462"
height="258" style="border: none" id="ctl00_ctl00_Content_Content_ctl4795"></div>
<p> If the Scheduler is grouped by resources, multi-resource appointments will appear under all selected resources. </p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-blazor-scheduler-multiple-resources-3.png"
srcset="/subscriptions/i/24.1/24-1-blazor-scheduler-multiple-resources-3.png 1x, /subscriptions/i/24.1/24-1-blazor-scheduler-multiple-resources-3@2x.png 2x" alt="Multi-Resource Appointments - Blazor Scheduler, DevExpress" width="970"
height="600" style="border: none" id="ctl00_ctl00_Content_Content_ctl4798"></div>
<p><a href="https://demos.devexpress.com/blazor/Scheduler/Resources/MultipleResources" target="_blank" rel="noopener" class="Button Gray">Online Demo</a></p> <span class="H-Separator"></span>
<h4 anchor="blazor-scheduler-scrollbars">
<a name="blazor-scheduler-scrollbars" class="anchor visible-anchor" href="#blazor-scheduler-scrollbars">#</a>Built-in Scroll Bars
</h4>
<p> The DevExpress Blazor Scheduler component now automatically displays a scroll bar when cells don't fit within control boundaries/size. To specify Scheduler boundaries/size, modify width/height parameters using CSS: </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">Razor</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="razor"><span class="hljs-tag"><<span class="hljs-name">style</span>></span><span class="language-css">
<span class="hljs-selector-class">.my-scheduler</span> {
<span class="hljs-attribute">height</span>: <span class="hljs-number">600px</span>;
}
</span><span class="hljs-tag"></<span class="hljs-name">style</span>></span>
<span class="hljs-tag"><<span class="hljs-name">DxScheduler</span> <span class="hljs-attr">...</span> <span class="hljs-attr">CssClass</span>=<span class="hljs-string">"my-scheduler"</span><span class="hljs-string">/</span>></span></code></pre>
</div>
</div> <span class="H-Separator"></span>
<h4 anchor="blazor-scheduler-scroll-api">
<a name="blazor-scheduler-scroll-api" class="anchor visible-anchor" href="#blazor-scheduler-scroll-api">#</a>Scroll API
</h4>
<p> v24.1 ships with a new <a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxScheduler.ScrollTo.overloads?v=24.1" target="_blank" rel="noopener">ScrollTo()</a> method. This method scrolls the view area to a specified date or
appointment. When used, <code data-renderer="hljs" class="csharp" data-control="Code-Inline">ScrollTo()</code> can help you focus user attention on the most important time/appointment/event within the currently displayed view (for
example, the beginning of a work day). </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">Razor</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="razor"><span class="hljs-tag"><<span class="hljs-name">DxScheduler</span> <span class="hljs-attr">...</span> @<span class="hljs-attr">ref</span>=<span class="hljs-string">"Scheduler"</span> /></span>
<span class="hljs-built_in">@code {</span><span class="language-csharp">
DxScheduler Scheduler { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
DesiredDate = <span class="hljs-keyword">new</span> DateTime(<span class="hljs-number">2024</span>, <span class="hljs-number">05</span>, <span class="hljs-number">14</span>)
<span class="hljs-comment">// ...</span>
<span class="hljs-function"><span class="hljs-keyword">protected</span> <span class="hljs-keyword">override</span> <span class="hljs-keyword">void</span> <span class="hljs-title">OnAfterRender</span>(<span class="hljs-params"><span class="hljs-built_in">bool</span> firstRender</span>)</span> {
<span class="hljs-keyword">base</span>.OnAfterRender(firstRender);
<span class="hljs-keyword">if</span> (firstRender) {
Scheduler.ScrollTo(DesiredDate);
}
}
</span><span class="hljs-built_in">}</span></code></pre>
</div>
</div> <span class="H-Separator"></span>
<h4 anchor="blazor-scheduler-recurrence-form">
<a name="blazor-scheduler-recurrence-form" class="anchor visible-anchor" href="#blazor-scheduler-recurrence-form">#</a>Recurrence Form Customization
</h4>
<p> We enhanced the Scheduler's <a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxScheduler.AppointmentFormShowing" target="_blank" rel="noopener">AppointmentFormShowing</a> event. It now allows you to customize recurrence
options for both Appointment and Recurrence forms. For instance, you can modify the list of items available in the Appointment form’s Repeat section as needs dictate: </p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-blazor-recurrence-form-customization.png"
srcset="/subscriptions/i/24.1/24-1-blazor-recurrence-form-customization.png 1x, /subscriptions/i/24.1/24-1-blazor-recurrence-form-customization@2x.png 2x" alt="Recurrence Form Customization - Blazor Scheduler, DevExpress" width="488"
height="228" style="border: none" id="ctl00_ctl00_Content_Content_ctl4836"></div>
<p> ...Or modify the list of repeat end items and weekday list in the Recurrence form: </p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-blazor-recurrence-form-customization-2.png"
srcset="/subscriptions/i/24.1/24-1-blazor-recurrence-form-customization-2.png 1x, /subscriptions/i/24.1/24-1-blazor-recurrence-form-customization-2@2x.png 2x" alt="Modify Repeat Modes - Blazor Scheduler, DevExpress" width="500"
height="426" style="border: none" id="ctl00_ctl00_Content_Content_ctl4839"></div>
<p> The following code snippet customizes the Scheduler's recurrence options: </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">Razor</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="razor"><span class="hljs-tag"><<span class="hljs-name">DxScheduler</span> <span class="hljs-attr">...</span> <span class="hljs-attr">AppointmentFormShowing</span>=<span class="hljs-string">"OnAppointmentFormShowing"</span><span class="hljs-string">/</span>></span>
void OnAppointmentFormShowing(SchedulerAppointmentFormEventArgs args) {
args.FormInfo.RepeatItems = new List<span class="hljs-tag"><<span class="hljs-name">SchedulerRecurrenceType</span>></span>() {
SchedulerRecurrenceType.Yearly,
SchedulerRecurrenceType.Weekly,
SchedulerRecurrenceType.Never
};
args.FormInfo.RecurrenceFormInfo.RepeatEndItems = new List<span class="hljs-tag"><<span class="hljs-name">SchedulerRecurrenceRange</span>></span>() {
SchedulerRecurrenceRange.OccurrenceCount,
SchedulerRecurrenceRange.EndByDate
};
args.FormInfo.RecurrenceFormInfo.WeekDayItems.Remove(SchedulerWeekDays.WeekendDays);
}
}</code></pre>
</div>
</div> <span class="H-Separator"></span>
<h4 anchor="blazor-scheduler-min-cell-width">
<a name="blazor-scheduler-min-cell-width" class="anchor visible-anchor" href="#blazor-scheduler-min-cell-width">#</a>Day, Week, WorkWeek Views – Minimum Cell Width
</h4>
<p> You can now specify the minimum width of a day cell in day, week, and work week views. Pass the integer value to the
<a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.Base.DxSchedulerDayViewBase.CellMinWidth" target="_blank" rel="noopener">CellMinWidth</a> property to set this width in pixels. </p> <span class="H-Separator"></span>
<h3 data-anchor="blazor-window-popup" data-toc-title="Window and Popup">
<a name="blazor-window-popup" class="anchor"></a>Window and Popup
</h3>
<h4 anchor="blazor-window-popup-dragdrop-multiple-elements">
<a name="blazor-window-popup-dragdrop-multiple-elements" class="anchor visible-anchor" href="#blazor-window-popup-dragdrop-multiple-elements">#</a>Drag And Drop Using Multiple Window Elements
</h4>
<p> Disable the new <a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxPopup.AllowDragByHeaderOnly?v=24.1" target="_blank" rel="noopener">DxPopup.AllowDragByHeaderOnly</a> /
<a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxWindow.AllowDragByHeaderOnly?v=24.1" target="_blank" rel="noopener">DxWindow.AllowDragByHeaderOnly</a> option to allow users to drag and drop a window by its header, body,
or footer. </p>
<p>
<a href="https://demos.devexpress.com/blazor/Window#Dragging" target="_blank" rel="noopener" class="Button Gray">Online Demo: Window</a><a href="https://demos.devexpress.com/blazor/Popup#Dragging" target="_blank" rel="noopener" class="Button Gray">Online Demo: Popup</a>
</p> <span class="H-Separator"></span>
<h3 data-anchor="blazor-survey" data-toc-title="Survey - Blazor">
<a name="blazor-survey" class="anchor"></a>Survey - Blazor
</h3>
<h4 anchor=""> Your Feedback Matters! </h4>
<div id="ctl00_ctl00_Content_Content_SurveyContainer" data-control="survey" class="InlineSurvey">
<div data-role="SurveyContent" data-markdown="false" data-partial="false" data-multiple-results="None" data-survey-id="958d9bd7-5f24-4c9f-8b05-0942fc4d7b39" data-auth-required="true"
data-user-data="{"IsLoggedIn":false,"IsEmployee":false,"CustomerId":null}" style="display: none;">
</div>
<div data-role="AuthRequired" style="display: block;"> Please <a href="https://www.devexpress.com/MyAccount/LogIn/?returnUrl=https%3a%2f%2fwww.devexpress.com%2fsubscriptions%2fwhats-new%2f">login</a> to complete the survey. </div>
<div data-role="Loading" style="display: none;">
<img src="../../Content/Editors/ajax-loader.gif" style="border-width:0px;">
</div>
<div data-role="Completed" style="display: none;">
<h3> Survey Completed </h3>
<p class="sys-max-width-md-80 sys-max-width-lg-60">Thank you for taking the time to complete this survey. Your responses have now been posted. If you want to follow up with additional information, feel free to send us an email at
<a href="mailto:clientservices@devexpress.com">clientservices@devexpress.com</a> anytime. </p>
</div>
<div data-role="AlreadyPassed" style="display: none;">
<h3> You've Already Completed This Survey </h3>
<p class="sys-max-width-md-80 sys-max-width-lg-60">Our records show that you have already completed this survey. If you want to follow up with additional information, send us an email at
<a href="mailto:clientservices@devexpress.com">clientservices@devexpress.com</a>.</p>
</div>
<div data-role="Expired" style="display: none;">
<h3> This survey has expired </h3>
<p>If you want to share your feedback or request new functionality, please submit a new support ticket via the <a href="https://supportcenter.devexpress.com/">DevExpress Support Center</a>. We’ll be happy to follow up.</p>
</div>
</div>
<h2 class="SectionHeader" data-anchor="reporting" data-toc-title="Reporting">
<a data-whatsnew-platform="reporting" name="reporting" class="anchor"></a>.NET Reporting v24.1
</h2>
<div class="WhatsNewTOC grid sys-visibility-hidden sys-visibility-hidden sys-visibility-sm-shown">
<div class="row">
<div class="col-sm-6 col-md-3 col-order-1">
<p><a href="#reporting-web"><span>Reporting for Web</span></a></p>
<p><a href="#reporting-blazor"><span>Reporting for Blazor</span></a></p>
</div>
<div class="col-sm-6 col-md-3 col-sm-order-3 col-md-order-2">
<p><a href="#reporting-common"><span>All Platforms</span></a></p>
<p><a href="#reporting-cloud-deployment"><span>Cloud Deployment</span></a></p>
</div>
<div class="column-break sm">
</div>
<div class="col-sm-6 col-md-3 col-sm-order-2 col-md-order-3">
<p><a href="#reporting-accessibility"><span>Accessibility</span></a></p>
<p><a href="#reporting-datasources"><span>Data Sources</span></a></p>
</div>
<div class="col-sm-6 col-md-3 col-order-4">
<p><a href="#reporting-survey"><span>Survey - Reporting</span></a></p>
</div>
</div>
</div>
<div class="Attention">
<p><strong>Your feedback matters.</strong><br> Please, review the description of <strong>DevExpress Reporting</strong>-related features below and leave your feedback at the end of the section. </p>
<p><a href="#reporting-survey">Go to the survey now.</a></p>
</div>
<h3 data-anchor="reporting-web" data-toc-title="Reporting for Web">
<a name="reporting-web" class="anchor"></a>Reporting for Web
</h3>
<h4 anchor="reporting-native-react-viewer">
<a name="reporting-native-react-viewer" class="anchor visible-anchor" href="#reporting-native-react-viewer">#</a>Native React Report Viewer Component
</h4>
<p> Our native React Report Viewer component leverages the internal architecture of the DevExpress Angular Report Viewer and associated assistive technologies. Our implementation delivers superior user experiences and improved performance
when compared to solutions based on JavaScript wrappers. Our new React Report Viewer ships with the following built-in customization capabilities: </p>
<p><strong>Toolbar Customization</strong></p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">JavaScript</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="javascript"><span class="hljs-string">'use client'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-title class_">React</span> <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-title class_">ReportViewer</span>, { <span class="hljs-title class_">Callbacks</span>, <span class="hljs-title class_">RequestSettings</span> } <span class="hljs-keyword">from</span> <span class="hljs-string">'devexpress-reporting-react/dx-report-viewer'</span>;
<span class="hljs-keyword">import</span> { <span class="hljs-title class_">TemplateEngine</span> } <span class="hljs-keyword">from</span> <span class="hljs-string">'devexpress-reporting-react/dx-report-viewer/core/template-engine'</span>;
<span class="hljs-keyword">import</span> { <span class="hljs-title class_">ActionId</span> } <span class="hljs-keyword">from</span> <span class="hljs-string">'devexpress-reporting/viewer/constants'</span>;
<span class="hljs-keyword">import</span> { <span class="hljs-title class_">CustomAction</span> } <span class="hljs-keyword">from</span> <span class="hljs-string">'devexpress-reporting/dx-webdocumentviewer'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"devextreme/dist/css/dx.light.css"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"@devexpress/analytics-core/dist/css/dx-analytics.common.css"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"@devexpress/analytics-core/dist/css/dx-analytics.light.css"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"devexpress-reporting/dist/css/dx-webdocumentviewer.css"</span>;
<span class="hljs-keyword">import</span> styles <span class="hljs-keyword">from</span> <span class="hljs-string">"./page.module.css"</span>;
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-keyword">function</span> <span class="hljs-title function_">Home</span>(<span class="hljs-params"></span>) {
<!--don<span class="hljs-string">'t remove this line/comment-->
const templateEngine = new TemplateEngine();
templateEngine.setTemplate('</span>slideshow<span class="hljs-string">', () => (
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" viewBox="0 0 24 24">
<polygon className="dxd-icon-fill" points="4,2 4,22 22,12 " />
</svg>
));
const handleCustomizeMenuActions = ({ sender, args }: { sender: any, args: any }) => {
let interval: any;
const action = new CustomAction({
text: "Run Slide Show",
imageTemplateName: "slideshow",
visible: true,
disabled: false,
selected: false,
clickAction: function () {
if (this.selected) {
clearInterval(interval);
this.selected = false;
return;
}
var model = sender.GetPreviewModel();
if (model) {
this.selected = true;
interval = setInterval(function () {
var pageIndex = model.GetCurrentPageIndex();
model.GoToPage(pageIndex + 1);
}, 2000);
}
}
});
args.Actions.push(action);
var highlightEditingFieldsAction = args.GetById(ActionId.HighlightEditingFields);
if (highlightEditingFieldsAction)
highlightEditingFieldsAction.visible = false;
};
return (
<main className={styles.main}>
<ReportViewer reportUrl="Report" templateEngine={templateEngine}>
<RequestSettings invokeAction="/DXXRDV" host="http://localhost:5065" />
<Callbacks CustomizeMenuActions={React.useCallback(handleCustomizeMenuActions,[])} />
</ReportViewer>
</main>
);
}</span></code></pre>
</div>
</div>
<p><a href="https://github.com/DevExpress-Examples/reporting-react-customize-viewer-toolbar" target="_blank" rel="noopener">Example: Reporting for React - Customize Viewer Toolbar</a></p>
<p><strong>Parameters Customization</strong></p>
<p> The following sample code declares a custom template for the Parameter Editor and applies validation rules to the NumberBox component (used to edit the "Age" report parameter value): </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">JavaScript</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="javascript"><span class="hljs-keyword">const</span> <span class="hljs-title function_">CustomizeParameterEditor</span> = (<span class="hljs-params">{data}: {data: IEditorViewModel}</span>) => (
<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">NumberBox</span> <span class="hljs-attr">showSpinButtons</span>=<span class="hljs-string">{true}</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{data.value}</span> <span class="hljs-attr">disabled</span>=<span class="hljs-string">{data.disabled}</span>></span>
<span class="hljs-tag"><<span class="hljs-name">Validator</span> <span class="hljs-attr">validationRules</span>=<span class="hljs-string">{data.validationRules}</span>></span>
<span class="hljs-tag"></<span class="hljs-name">Validator</span>></span>
<span class="hljs-tag"></<span class="hljs-name">NumberBox</span>></span></span>
);
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-keyword">function</span> <span class="hljs-title function_">Home</span>(<span class="hljs-params"></span>) {
<span class="hljs-keyword">const</span> templateEngine = <span class="hljs-keyword">new</span> <span class="hljs-title class_">TemplateEngine</span>();
templateEngine.<span class="hljs-title function_">setTemplate</span>(<span class="hljs-string">'custom-parameter-editor'</span>, <span class="hljs-title class_">CustomizeParameterEditor</span>);
<span class="hljs-keyword">const</span> handleCustomizeParameterEditors = <span class="hljs-title class_">React</span>.<span class="hljs-title function_">useCallback</span>((<span class="hljs-attr">event</span>: any): <span class="hljs-function"><span class="hljs-params">void</span> =></span> {
<span class="hljs-keyword">const</span> parameter = event.<span class="hljs-property">args</span>.<span class="hljs-property">parameter</span>;
<span class="hljs-keyword">const</span> info = event.<span class="hljs-property">args</span>.<span class="hljs-property">info</span>;
<span class="hljs-keyword">const</span> curYear = <span class="hljs-keyword">new</span> <span class="hljs-title class_">Date</span>().<span class="hljs-title function_">getFullYear</span>();
<span class="hljs-keyword">if</span> (parameter.<span class="hljs-property">type</span> === <span class="hljs-string">'CustomParameterType'</span>) {
info.<span class="hljs-property">validationRules</span> = info.<span class="hljs-property">validationRules</span> || [];
info.<span class="hljs-property">validationRules</span>.<span class="hljs-title function_">push</span>({
<span class="hljs-attr">type</span>: <span class="hljs-string">'range'</span>,
<span class="hljs-attr">min</span>: <span class="hljs-number">1900</span>,
<span class="hljs-attr">max</span>: curYear,
<span class="hljs-attr">message</span>: <span class="hljs-string">`The Birth Year parameter value should be in a range from 1900 to <span class="hljs-subst">${curYear}</span>.`</span>
});
info.<span class="hljs-property">editor</span>.<span class="hljs-property">header</span> = <span class="hljs-string">"custom-parameter-editor"</span>;
}
}, []);
<span class="hljs-keyword">return</span> (
<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">main</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.main}</span>></span>
<span class="hljs-tag"><<span class="hljs-name">ReportViewer</span> <span class="hljs-attr">reportUrl</span>=<span class="hljs-string">"CustomParameterReport"</span> <span class="hljs-attr">templateEngine</span>=<span class="hljs-string">{templateEngine}</span>></span>
<span class="hljs-tag"><<span class="hljs-name">RequestSettings</span> <span class="hljs-attr">invokeAction</span>=<span class="hljs-string">"/DXXRDV"</span> <span class="hljs-attr">host</span>=<span class="hljs-string">"http://localhost:2119/"</span> /></span>
<span class="hljs-tag"><<span class="hljs-name">Callbacks</span> <span class="hljs-attr">CustomizeParameterEditors</span>=<span class="hljs-string">{handleCustomizeParameterEditors}</span> /></span>
<span class="hljs-tag"></<span class="hljs-name">ReportViewer</span>></span>
<span class="hljs-tag"></<span class="hljs-name">main</span>></span></span>
);
}</code></pre>
</div>
</div>
<p></p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-reporting-for-react-parameters-customization.png"
srcset="/subscriptions/i/24.1/24-1-reporting-for-react-parameters-customization.png 1x, /subscriptions/i/24.1/24-1-reporting-for-react-parameters-customization@2x.png 2x" alt="Native React Report Viewer Component, DevExpress Reports"
width="967" height="255" style="border: none" id="ctl00_ctl00_Content_Content_ctl5505"></div>
<p></p>
<p>
<a href="https://docs.devexpress.com/XtraReports/119338/web-reporting/react-reporting/document-viewer/integration/document-viewer-integration-in-react?v=24.1" target="_blank" rel="noopener">Documentation: Create a React Application with Web Document Viewer (Next.js)</a>
</p> <span class="H-Separator"></span>
<h4 anchor="reporting-angular-toolbar-api">
<a name="reporting-angular-toolbar-api" class="anchor visible-anchor" href="#reporting-angular-toolbar-api">#</a>Native Angular Report Viewer
</h4>
<p><strong>Toolbar Customization API</strong></p>
<p> With this release, our <a href="https://docs.devexpress.com/XtraReports/401914/web-reporting/angular-reporting#document-viewer" target="_blank" rel="noopener">Angular Report Viewer</a> allows you to customize its built-in toolbar as
requirements dictate. The following code snippet hides a toolbar item using the
<a href="https://docs.devexpress.com/XtraReports/DevExpress.AspNetCore.Reporting.WebDocumentViewer.WebDocumentViewerClientSideEventsBuilder.CustomizeMenuActions(System.String)#angular" target="_blank" rel="noopener">CustomizeMenuActions</a>
event handler: </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active"></li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="TypeScript"><span class="hljs-title class_">CustomizeMenuActions</span>(event) {
<span class="hljs-keyword">var</span> actionSearch = event.<span class="hljs-property">args</span>.<span class="hljs-title class_">GetById</span>(<span class="hljs-title class_">ActionId</span>.<span class="hljs-property">Search</span>);
<span class="hljs-keyword">if</span> (actionSearch)
actionSearch.<span class="hljs-property">visible</span> = <span class="hljs-literal">false</span>;
}
<span class="hljs-keyword">var</span> highlightEditingFieldsAction = e.<span class="hljs-title class_">GetById</span>(<span class="hljs-title class_">DevExpress</span>.<span class="hljs-property">Reporting</span>.<span class="hljs-property">Viewer</span>.<span class="hljs-property">ActionId</span>.<span class="hljs-property">HighlightEditingFields</span>);
<span class="hljs-keyword">if</span> (highlightEditingFieldsAction)
highlightEditingFieldsAction.<span class="hljs-property">visible</span> = <span class="hljs-literal">false</span>;
}</code></pre>
</div>
</div>
<p> The following code snippet adds a custom export option to the toolbar using the same event handler: </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active"></li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="TypeScript"><span class="hljs-keyword">function</span> <span class="hljs-title function_">CustomizeMenuActions</span>(<span class="hljs-params">event</span>) {
<span class="hljs-keyword">const</span> actionExportTo = event.<span class="hljs-property">args</span>.<span class="hljs-title class_">GetById</span>(<span class="hljs-title class_">ActionId</span>.<span class="hljs-property">ExportTo</span>);
<span class="hljs-keyword">const</span> newFormat = { <span class="hljs-attr">format</span>: <span class="hljs-string">'NewFormat'</span>, <span class="hljs-attr">text</span>: <span class="hljs-string">'New Format'</span> };
<span class="hljs-keyword">if</span> (actionExportTo) {
actionExportTo.<span class="hljs-property">events</span>.<span class="hljs-title function_">on</span>(<span class="hljs-string">'propertyChanged'</span>, <span class="hljs-function">(<span class="hljs-params">args</span>) =></span> {
<span class="hljs-keyword">const</span> formats = actionExportTo.<span class="hljs-property">items</span>[<span class="hljs-number">0</span>].<span class="hljs-property">items</span>;
<span class="hljs-keyword">if</span> (args.<span class="hljs-property">propertyName</span> === <span class="hljs-string">'items'</span> &amp;&amp; formats.<span class="hljs-title function_">indexOf</span>(newFormat) === -<span class="hljs-number">1</span>) {
formats.<span class="hljs-title function_">push</span>(newFormat);
}
});
}
}</code></pre>
</div>
</div>
<p><strong>OnPush Change Detection Strategy Support</strong></p>
<p> v24.1 also adds support for <a href="https://angular.io/api/core/ChangeDetectionStrategy" target="_blank" rel="noopener">OnPush Change Detection Strategy</a>. Angular's OnPush change detection strategy improves performance by reducing
unnecessary rendering cycles and only triggering change detection when input references change. With this update, you can change the detection strategy from default to <code data-renderer="hljs" class="csharp"
data-control="Code-Inline">ChangeDetectionStrategy.OnPush</code> by adding the <code data-renderer="hljs" class="csharp" data-control="Code-Inline">changeDetection</code> property in the <code data-renderer="hljs" class="csharp"
data-control="Code-Inline">@Component</code> decorator as follows: </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active"></li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="TypeScript"><span class="hljs-keyword">import</span> { <span class="hljs-title class_">Component</span>, <span class="hljs-title class_">ViewEncapsulation</span> } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/core'</span>;
<span class="hljs-keyword">import</span> { <span class="hljs-title class_">CommonModule</span> } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/common'</span>;
<span class="hljs-keyword">import</span> { <span class="hljs-title class_">RouterOutlet</span> } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/router'</span>;
<span class="hljs-keyword">import</span> { <span class="hljs-title class_">DxReportViewerModule</span> } <span class="hljs-keyword">from</span> <span class="hljs-string">'devexpress-reporting-angular'</span>;
<span class="hljs-meta">@Component</span> ({
<span class="hljs-attr">selector</span>: <span class="hljs-string">'app-root'</span>,
<span class="hljs-attr">changeDetection</span>: <span class="hljs-title class_">ChangeDetectionStrategy</span>.<span class="hljs-property">OnPush</span>,
<span class="hljs-attr">encapsulation</span>: <span class="hljs-title class_">ViewEncapsulation</span>.<span class="hljs-property">None</span>,
<span class="hljs-attr">standalone</span>: <span class="hljs-literal">true</span>,
<span class="hljs-attr">imports</span>: [
<span class="hljs-title class_">CommonModule</span>,
<span class="hljs-title class_">RouterOutlet</span>,
<span class="hljs-title class_">DxReportViewerModule</span>
],
<span class="hljs-attr">templateUrl</span>: <span class="hljs-string">'./app.component.html'</span>,
<span class="hljs-attr">styleUrls</span>: [...]
})
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">AppComponent</span> {
title = <span class="hljs-string">'DXReportViewerSample'</span>;
<span class="hljs-attr">reportUrl</span>: <span class="hljs-built_in">string</span> = <span class="hljs-string">'TestReport'</span>;
<span class="hljs-attr">hostUrl</span>: <span class="hljs-built_in">string</span> = <span class="hljs-string">'https://localhost:5001/'</span>;
<span class="hljs-attr">invokeAction</span>: <span class="hljs-built_in">string</span> = <span class="hljs-string">'/DXXRDV'</span>;
}</code></pre>
</div>
</div> <span class="H-Separator"></span>
<h4 anchor="reporting-parameters-panel">
<a name="reporting-parameters-panel" class="anchor visible-anchor" href="#reporting-parameters-panel">#</a>New Standalone Parameters Panel Component for ASP.NET Core, Blazor, Angular
</h4>
<p> Our new <a href="https://docs.devexpress.com/XtraReports/404883/web-reporting/standalone-parameters-panel?v=24.1" target="_blank" rel="noopener">Report Parameters Panel</a> component automatically generates a layout for report
parameter editors (including associated grouping) based on a report instance supplied from the backend. </p>
<p> This component addresses a variety of usage scenarios, including the need to programmatically create a report and export it or send it by mail - without displaying its print preview to an end-user. Our Standalone Parameters Panel
helps reduce an app’s overall memory footprint because it eliminates the need to generate report images in the background and send them to a client app. </p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-reporting-parameters-panel-arrowed.png"
srcset="/subscriptions/i/24.1/24-1-reporting-parameters-panel-arrowed.png 1x, /subscriptions/i/24.1/24-1-reporting-parameters-panel-arrowed@2x.png 2x"
alt="New Standalone Parameters Panel Component for ASP.NET Core, Blazor, Angular - DevExpress Reports" width="780" height="456" style="border: none" id="ctl00_ctl00_Content_Content_ctl5558"></div>
<p> Component implementation is based on the Parameters Panel in our Report Viewer component. As such, it gives you access to the same set of component public properties and events related to report parameters. Here's a sample component
definition for the Angular platform: </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active"></li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="HTML"><span class="hljs-tag"><<span class="hljs-name">dx-report-parameters-panel</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"parametersPanel"</span> [<span class="hljs-attr">reportUrl</span>]=<span class="hljs-string">"yourReportName"</span> <span class="hljs-attr">height</span>=<span class="hljs-string">"560px"</span> <span class="hljs-attr">width</span>=<span class="hljs-string">"400px"</span>></span>
<span class="hljs-tag"><<span class="hljs-name">dxrpp-request-options</span> [<span class="hljs-attr">invokeAction</span>]=<span class="hljs-string">"invokeAction"</span> <span class="hljs-attr">host</span>=<span class="hljs-string">"http://yourhostname:port/"</span>></span><span class="hljs-tag"></<span class="hljs-name">dxrpp-request-options</span>></span>
<span class="hljs-tag"><<span class="hljs-name">dxrpp-callbacks</span> (<span class="hljs-attr">BeforeRender</span>)=<span class="hljs-string">"onBeforeRender($event)"</span>></span><span class="hljs-tag"></<span class="hljs-name">dxrpp-callbacks</span>></span>
<span class="hljs-tag"></<span class="hljs-name">dx-report-parameters-panel</span>></span></code></pre>
</div>
</div>
<p> The panel allows you to create custom submit buttons and handle associated click events. This will give you the ability to serialize input parameter values, send them to the backend app, and then apply them to an instance of the <code
data-renderer="hljs" class="csharp" data-control="Code-Inline">XtraReport</code> class (before printing or export operations): </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active"></li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="TypeScript"><span class="hljs-title function_">onBeforeRender</span>(<span class="hljs-params">event</span>) {
<span class="hljs-variable language_">this</span>.<span class="hljs-property">sender</span> = event.<span class="hljs-property">sender</span>;
<span class="hljs-keyword">const</span> panel = <span class="hljs-variable language_">this</span>.<span class="hljs-property">sender</span>.<span class="hljs-title class_">GetParametersModel</span>();
panel.<span class="hljs-property">buttons</span>.<span class="hljs-title function_">push</span>({
<span class="hljs-attr">text</span>: <span class="hljs-string">'Export'</span>,
<span class="hljs-attr">onClick</span>: <span class="hljs-keyword">async</span> () => {
<span class="hljs-keyword">const</span> data = <span class="hljs-variable language_">this</span>.<span class="hljs-property">sender</span>.<span class="hljs-title class_">SerializeParametersState</span>();
<span class="hljs-keyword">const</span> formData = <span class="hljs-keyword">new</span> <span class="hljs-title class_">FormData</span>();
formData.<span class="hljs-title function_">append</span>(<span class="hljs-string">'serializedParameters'</span>, data);
formData.<span class="hljs-title function_">append</span>(<span class="hljs-string">'reportUrl'</span>, <span class="hljs-variable language_">this</span>.<span class="hljs-property">reportUrl</span>);
<span class="hljs-keyword">const</span> result = <span class="hljs-keyword">await</span> <span class="hljs-title function_">fetch</span>(<span class="hljs-string">`<span class="hljs-subst">${<span class="hljs-variable language_">this</span>.host}</span>/ExportWithParameters`</span>, {
<span class="hljs-attr">method</span>: <span class="hljs-string">'POST'</span>,
<span class="hljs-attr">body</span>: formData
}).<span class="hljs-title function_">then</span>(<span class="hljs-function"><span class="hljs-params">response</span> =></span> response.<span class="hljs-title function_">json</span>());
<span class="hljs-title function_">alert</span>(result.<span class="hljs-property">message</span>);
}
}, {
<span class="hljs-attr">text</span>: <span class="hljs-string">'Send Email'</span>,
<span class="hljs-attr">onClick</span>: <span class="hljs-function">() =></span> {
<span class="hljs-title function_">alert</span>(<span class="hljs-string">'Email sent'</span>);
}
});
panel.<span class="hljs-property">showButtons</span> = <span class="hljs-literal">true</span>;
}</code></pre>
</div>
</div>
<p> The following code snippet applies parameter values on the backend: </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">C#</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="csharp"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">async</span> Task<IActionResult> <span class="hljs-title">ExportWithParameters</span>(<span class="hljs-params">
[FromServices]IReportParametersSerializer reportParametersSerializer,
[FromForm]<span class="hljs-built_in">string</span> serializedParameters,
[FromForm]<span class="hljs-built_in">string</span> reportUrl</span>)</span> {
<span class="hljs-keyword">var</span> report = <span class="hljs-keyword">await</span> reportParametersSerializer.ApplyParametersStateAsync(reportUrl, serializedParameters);
report.ExportToPdf(<span class="hljs-string">"yourFilePath"</span>);
<span class="hljs-keyword">return</span> Ok(<span class="hljs-keyword">new</span> { Message = <span class="hljs-string">"A report has been successfully exported"</span> });
}</code></pre>
</div>
</div>
<p><a href="https://github.com/DevExpress-Examples/reporting-asp-net-core-standalone-parameters-panel" target="_blank" rel="noopener" class="Button Gray">Example</a></p> <span class="H-Separator"></span>
<h4 anchor="reporting-web-designer">
<a name="reporting-web-designer" class="anchor visible-anchor" href="#reporting-web-designer">#</a>Web Report Designer - Hide/Restrict Parameter Editing
</h4>
<p> We introduced a new set of APIs to help customize edit settings for parameters, parameter groups, and parameter separators. This API will be of value when creating a set of "canned" or predefined reports with mandatory/hidden
parameters. </p>
<p> The new <a href="https://docs.devexpress.com/XtraReports/DevExpress.XtraReports.Web.ReportDesigner.ReportDesignerParameterEditingSettings?v=24.1" target="_blank" rel="noopener">ParameterEditingSettings</a> class contains the following
settings that affect the Properties Panel, Field List and Parameter Editor: </p>
<ul>
<li><a href="https://docs.devexpress.com/XtraReports/DevExpress.XtraReports.Web.ReportDesigner.ReportDesignerParameterEditingSettings.AllowEditParameterCollection?v=24.1" target="_blank" rel="noopener">AllowEditParameterCollection</a> -
Hides parameter add and delete buttons.</li>
<li><a href="https://docs.devexpress.com/XtraReports/DevExpress.XtraReports.Web.ReportDesigner.ReportDesignerParameterEditingSettings.AllowEditParameterGroups?v=24.1" target="_blank" rel="noopener">AllowEditParameterGroups</a> - Hides
parameter group add and delete buttons.</li>
<li><a href="https://docs.devexpress.com/XtraReports/DevExpress.XtraReports.Web.ReportDesigner.ReportDesignerParameterEditingSettings.AllowEditParameterSeparators?v=24.1" target="_blank" rel="noopener">AllowEditParameterSeparators</a> -
Hides parameter separator add and delete buttons.</li>
<li><a href="https://docs.devexpress.com/XtraReports/DevExpress.XtraReports.Web.ReportDesigner.ReportDesignerParameterEditingSettings.AllowEditProperties?v=24.1" target="_blank" rel="noopener">AllowEditProperties</a> - Disables
properties editors for parameter and groups.</li>
<li><a href="https://docs.devexpress.com/XtraReports/DevExpress.XtraReports.Web.ReportDesigner.ReportDesignerParameterEditingSettings.AllowReorderParameters?v=24.1" target="_blank" rel="noopener">AllowReorderParameters</a> - Hides the
up and down buttons and disables drag-n-drop operations.</li>
</ul>
<p> The following code snippet turns parameters, parameter groups and separators to read-only for an ASP.NET Core application (users can't add/delete parameters/groups/separators, edit/reorder associated properties): </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">Razor</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="razor"><span class="hljs-built_in">@{</span><span class="language-csharp">
<span class="hljs-keyword">var</span> designerRender = Html.DevExpress().ReportDesigner(<span class="hljs-string">"reportDesigner"</span>)
.ParameterEditingSettings( configure => {
configure.AllowEditParameterCollection = <span class="hljs-literal">false</span>;
configure.AllowEditParameterSeparators = <span class="hljs-literal">false</span>;
configure.AllowEditParameterGroups = <span class="hljs-literal">false</span>;
configure.AllowEditProperties = <span class="hljs-literal">false</span>;
configure.AllowReorderParameters = <span class="hljs-literal">false</span> })
.Height(<span class="hljs-string">"100%"</span>)
.Bind(<span class="hljs-string">"TestReport"</span>);
</span><span class="hljs-built_in">@</span><span class="language-csharp">designerRender.RenderHtml()</span><span class="language-csharp">
</span><span class="hljs-built_in">}</span></code></pre>
</div>
</div>
<p> We also introduced a new <code data-renderer="hljs" class="csharp" data-control="Code-Inline">CustomizeParameterProperties</code> event that allows you to customize a specific parameter or disable/hide specific properties editors at
the web Report Designer level. </p>
<p> For instance, the following code snippet hides the Allow Null Value property editor for all parameters (both in the Properties Panel and Parameter Editor) and hides the delete button for parameter groups: </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active"></li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="JavaScript"><span class="hljs-keyword">function</span> <span class="hljs-title function_">customizeParameterProperties</span>(<span class="hljs-params">s, e</span>) {
<span class="hljs-keyword">if</span> (e.<span class="hljs-property">parameter</span>) {
<span class="hljs-keyword">let</span> allowNullInfo = e.<span class="hljs-title function_">getEditor</span>(<span class="hljs-string">'allowNull'</span>);
<span class="hljs-keyword">if</span> (allowNullInfo) {
allowNullInfo.<span class="hljs-property">visible</span> = <span class="hljs-literal">false</span>;
}
}
<span class="hljs-keyword">if</span> (e.<span class="hljs-property">parameterPanelLayoutItem</span>.<span class="hljs-property">layoutItemType</span> === <span class="hljs-string">'Group'</span>) {
e.<span class="hljs-property">editOptions</span>.<span class="hljs-property">allowDelete</span> = <span class="hljs-literal">false</span>;
}
}</code></pre>
</div>
</div>
<p>
<a href="https://docs.devexpress.com/XtraReports/404935/web-reporting/asp-net-core-reporting/end-user-report-designer-in-asp-net-applications/customize-the-report-designer/specify-parameter-editing-settings?v=24.1" target="_blank" rel="noopener">Documentation</a>
</p> <span class="H-Separator"></span>
<h3 data-anchor="reporting-blazor" data-toc-title="Reporting for Blazor">
<a name="reporting-blazor" class="anchor"></a>Reporting for Blazor
</h3>
<h4 anchor="reporting-blazor-viewer-send-email">
<a name="reporting-blazor-viewer-send-email" class="anchor visible-anchor" href="#reporting-blazor-viewer-send-email">#</a>Report Viewer - Send an Email
</h4>
<p> We created an example that uses the <a href="https://mimekit.net/docs/html/Introduction.htm" target="_blank" rel="noopener">Mailkit</a> library to send an email from our Native Blazor Report Viewer. </p>
<p> The "Send Email" button in the Viewer's toolbar opens a <a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxPopup" target="_blank" rel="noopener">DxPopup</a>. In the "Send Email" window, you can specify a recipient list,
subject, attachment, and body. Click the "Send" button to send the report with the specified settings. </p>
<p><span class="FootNote"> * The <a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxPopup" target="_blank" rel="noopener">DxPopup</a> component is available in ASP.NET & Blazor Subscription. </span></p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-reporting-for-blazor-send-email.png"
srcset="/subscriptions/i/24.1/24-1-reporting-for-blazor-send-email.png 1x, /subscriptions/i/24.1/24-1-reporting-for-blazor-send-email@2x.png 2x" alt="Blazor Report Viewer — Send an Email, DevExpress" width="960" height="720"
style="border: none" id="ctl00_ctl00_Content_Content_ctl5625"></div>
<p><a href="https://github.com/DevExpress-Examples/reporting-blazor-email-report/" target="_blank" rel="noopener" class="Button Gray">Example</a></p> <span class="H-Separator"></span>
<h3 data-anchor="reporting-common" data-toc-title="All Platforms">
<a name="reporting-common" class="anchor"></a>All Platforms
</h3>
<h4 anchor="reporting-svg-export">
<a name="reporting-svg-export" class="anchor visible-anchor" href="#reporting-svg-export">#</a>SVG Export
</h4>
<p> v24.1 ships with a new SVG export option. When enabled, it allows users to save reports as a collection of scalable vector graphics (SVG) images. This new export format will produce high-quality vector report page images without loss
of text content quality. SVG export will be of value for those who wish to modify/share report images or embed report thumbnails on web pages (since the SVG format is fully compatible with modern browsers). </p> <p></p>
<div data-control="image-comparer" data-comparer-theme="dark" data-label-before="Export to PNG" data-label-after="Export to SVG" data-comparer-position="50" class="icv icv__icv--horizontal standard"><img
src="/subscriptions/i/24.1/24-1-reporting-export-png.png" srcset="/subscriptions/i/24.1/24-1-reporting-export-png.png 1x, /subscriptions/i/24.1/24-1-reporting-export-png@2x.png 2x" alt="Export to PNG - DevExpress Reporting"
width="1170" height="529" style="border: none; width: 810px; height: 732.438px;" id="ctl00_ctl00_Content_Content_ctl5953" class="icv__img icv__img-a"><span class="icv__label icv__label-before keep">Export to PNG</span><span
class="icv__label icv__label-after keep">Export to SVG</span>
<div class="icv__wrapper" style="width: 50%; height: 50%; transition: all 100ms ease-out 0s;"><img src="/subscriptions/i/24.1/24-1-reporting-export-svg.png"
srcset="/subscriptions/i/24.1/24-1-reporting-export-svg.png 1x, /subscriptions/i/24.1/24-1-reporting-export-svg@2x.png 2x" alt="Export to SVG - DevEpress Reporting" width="1170" height="529"
style="border: none; width: 810px; height: 732.438px;" id="ctl00_ctl00_Content_Content_ctl5954" class="icv__img icv__img-b"></div>
<div class="icv__control" style="width: 50px; left: calc(50% - 25px); transition: all 100ms ease-out 0s;">
<div class="icv__control-line" style="width: 2px; background: rgb(48, 48, 48); box-shadow: rgba(0, 0, 0, 0.33) 0px 0px 15px;"></div>
<div class="icv__theme-wrapper">
<div class="icv__arrow-wrapper" style="transform: translateX(8px);"><svg height="15" width="15" style="
transform:
scale(1.5)
rotateZ(180deg); height: 20px; width: 20px;
-webkit-filter: drop-shadow( 0px 3px 5px rgba(0, 0, 0, .33));
filter: drop-shadow( 0px -3px 5px rgba(0, 0, 0, .33));
" xmlns="http://www.w3.org/2000/svg" data-name="Layer 1" viewBox="0 0 15 15">
<path fill="#303030" stroke="#303030" stroke-linecap="round" stroke-width="0" d="M4.5 1.9L10 7.65l-5.5 5.4"></path>
</svg></div>
<div class="icv__arrow-wrapper" style="transform: translateX(-8px);"><svg height="15" width="15" style="
transform:
scale(1.5)
rotateZ(0deg); height: 20px; width: 20px;
-webkit-filter: drop-shadow( 0px 3px 5px rgba(0, 0, 0, .33));
filter: drop-shadow( 0px 3px 5px rgba(0, 0, 0, .33));
" xmlns="http://www.w3.org/2000/svg" data-name="Layer 1" viewBox="0 0 15 15">
<path fill="#303030" stroke="#303030" stroke-linecap="round" stroke-width="0" d="M4.5 1.9L10 7.65l-5.5 5.4"></path>
</svg></div>
</div>
<div class="icv__control-line" style="width: 2px; background: rgb(48, 48, 48); box-shadow: rgba(0, 0, 0, 0.33) 0px 0px 15px;"></div>
</div>
</div>
<p></p> <p><a href="/subscriptions/i/24.1/24-1-reporting-svg-export.svg" target="_blank" rel="noopener">Open SVG file (Export Result)</a></p> <span class="H-Separator"></span>
<h4 anchor="reporting-expression-func">
<a name="reporting-expression-func" class="anchor visible-anchor" href="#reporting-expression-func">#</a>New Expression Functions
</h4>
<p> We added the following new expression functions to criteria language syntax used in DevExpress Reports: </p>
<ul>
<li><code data-renderer="hljs" class="csharp" data-control="Code-Inline">PrevRowColumnValue(<span class="hljs-built_in">string</span> columnName)</code> — Allows users to retrieve the value of the previous column/row. The function call
returns the same record if it is the first record in the data source.</li>
<li><code data-renderer="hljs" class="csharp" data-control="Code-Inline">NextRowColumnValue(<span class="hljs-built_in">string</span> columnName)</code> — Allows users to retrieve the value of the next column/row. The function call
returns the same record if it is the latest record in the data source.</li>
<li><code data-renderer="hljs" class="csharp" data-control="Code-Inline">GroupIndex(<span class="hljs-built_in">int</span> level)</code> — Allows users to retrieve the current group index.</li>
<li><code data-renderer="hljs" class="csharp" data-control="Code-Inline">CurrentRowIndexInGroup()</code> — Allows users to retrieve the current row index within a group.</li>
</ul>
<p> Functions are applicable to report control properties whose values can be set via expression binding. They are especially useful when you need to hide first or last records within a group, or highlight these records (i.e., modify
appearance properties like Font, BackColor, etc.). Obtaining the group index or the row index within a group is helpful when you need to display group numbering in the group header or record numbering within the group itself. The
introduction of <code data-renderer="hljs" class="csharp" data-control="Code-Inline">PrevRowColumnValue</code> and <code data-renderer="hljs" class="csharp" data-control="Code-Inline">NextRowColumnValue</code> functions also simplifies
migration from Microsoft SSRS and Crystal Reports, where their counterparts exist. </p>
<p> The following example generates a report with a multi-level numbered list. To achieve this report layout, report controls use <code data-renderer="hljs" class="csharp" data-control="Code-Inline">GroupIndex</code> and <code
data-renderer="hljs" class="csharp" data-control="Code-Inline">CurrentRowIndexInGroup</code> functions within data binding expressions (to return group and row indexes). </p>
<p> The following image illustrates output for a report designed to group information by product category and discontinued state (Review the following help topic for more information:
<a href="https://docs.devexpress.com/XtraReports/404915/detailed-guide-to-devexpress-reporting/use-expressions/expressions-tasks-and-solutions/group-numbering-by-index?v=24.1" target="_blank" rel="noopener">Group Numbering by Index</a>.):
</p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-reporting-new-functions.png" srcset="/subscriptions/i/24.1/24-1-reporting-new-functions.png 1x, /subscriptions/i/24.1/24-1-reporting-new-functions@2x.png 2x"
alt="Group Information by Product Category - DevExpress Reports" width="804" height="702" style="border: none" id="ctl00_ctl00_Content_Content_ctl5673"></div>
<p><a href="https://docs.devexpress.com/XtraReports/403363/detailed-guide-to-devexpress-reporting/use-expressions/functions-in-expressions?v=24.1#reporting-functions" target="_blank" rel="noopener">Documentation</a></p> <span
class="H-Separator"></span>
<h4 anchor="reporting-parameters-localization">
<a name="reporting-parameters-localization" class="anchor visible-anchor" href="#reporting-parameters-localization">#</a>Parameters Localization Enhancements
</h4>
<p> With our built-in DevExpress Reports localization engine, individuals using our Report Designer can now localize the titles of parameter groups displayed within the Parameters Panel across all supported platforms. </p>
<p> Descriptions for lookup parameter static values are also localizable. </p> <span class="H-Separator"></span>
<h3 data-anchor="reporting-cloud-deployment" data-toc-title="Cloud Deployment">
<a name="reporting-cloud-deployment" class="anchor"></a>Cloud Deployment
</h3>
<h4 anchor="reporting-skia-optimized-performance">
<a name="reporting-skia-optimized-performance" class="anchor visible-anchor" href="#reporting-skia-optimized-performance">#</a>Skia-Based Graphics Engine (non-Windows Environment) - Performance Enhancements
</h4>
<p> We refactored the implementation of our cross-platform drawing engine: we added caching for font internals and optimized dynamic memory allocation. Our internal tests indicate the following improvements when generating a 1500-page
text-based report (average of 25 iterations): </p>
<ul>
<li>Time taken to create a report document has decreased by approximately 20% (9 sec vs. 11 sec).</li>
<li>Time taken to export the report to PDF has decreased by approximately 16% (7.25 sec vs. 8.7 sec).</li>
<li>Time taken to export the report to an image has decreased by approximately 10% (5.2 sec vs. 5.7 sec).</li>
</ul>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-reporting-skia-performance.png" srcset="/subscriptions/i/24.1/24-1-reporting-skia-performance.png 1x, /subscriptions/i/24.1/24-1-reporting-skia-performance@2x.png 2x"
alt="Skia-Based Graphics Engine (non-Windows Environment)" width="629" height="392" style="border: none" id="ctl00_ctl00_Content_Content_ctl5699"></div>
<p> We also discovered that the overall CPU usage decreased by approximately 8-10%. </p>
<p><strong>Note</strong>: Performance enhancements are most pronounced for large report documents with lots of text. </p> <span class="H-Separator"></span>
<h4 anchor="reporting-web-tutorials">
<a name="reporting-web-tutorials" class="anchor visible-anchor" href="#reporting-web-tutorials">#</a>Microsoft Azure and Amazon Web Services App Deployment Tutorials
</h4>
<p> We created and published a set of help topics designed to simplify the deployment of DevExpress Reports-powered web apps to Microsoft Azure and AWS. Tutorials include: </p>
<p><strong>Microsoft Azure</strong></p>
<ul>
<li>The deployment of an ASP.NET Core Reporting app via Visual Studio to Azure App Service (Linux)</li>
<li>The deployment of a dockerized ASP.NET Core Reporting app via Visual Studio/CLI to Azure App Service (Linux)</li>
<li>The deployment of an Azure Functions App (Linux-based) with the Reporting capabilities</li>
<li>The usage of the Azure Storage Cache to store report documents</li>
</ul>
<p><strong>Amazon Web Services (AWS)</strong>: </p>
<ul>
<li>The deployment of a dockerized ASP.NET Core Reporting app (Linux-based) to AWS Elastic Container Service using the AWS Fargate</li>
<li>The deployment of an AWS Lambda function app</li>
<li>The creation and deployment of a REST API application with Reporting capabilities to AWS Lambda</li>
</ul>
<p> We encourage you to review these new topics: <a href="https://docs.devexpress.com/XtraReports/404819/cloud-integration" target="_blank" rel="noopener">DevExpress Reporting — Cloud Integration</a>. </p> <span
class="H-Separator"></span>
<h4 anchor="reporting-azure-updated-references">
<a name="reporting-azure-updated-references" class="anchor visible-anchor" href="#reporting-azure-updated-references">#</a>Reporting for Microsoft Azure — Updated References
</h4>
<p> We have refactored our internal implementation of services responsible for communicating with the Azure Service Bus and Azure Storage. These services are designed to host multi-instance ASP.NET Web Forms, MVC, and ASP.NET Core web
apps with DevExpress Reports on Microsoft Azure. They also allow you to cache report documents in Azure Table and Azure Blob storage. Our implementation now uses the most recent versions of the following NuGet packages. </p>
<p></p>
<ul>
<li><a href="https://www.nuget.org/packages/Azure.Data.Tables" target="_blank" rel="noopener">Azure.Data.Tables v12.8.3</a></li>
<li><a href="https://www.nuget.org/packages/Azure.Storage.Blobs" target="_blank" rel="noopener">Azure.Storage.Blobs v7.17.4</a></li>
<li><a href="https://www.nuget.org/packages/Azure.Messaging.ServiceBus" target="_blank" rel="noopener">Azure.Messaging.ServiceBus v12.19.1</a></li>
</ul>
<p></p>
<p>
<a href="https://docs.devexpress.com/XtraReports/10769/cloud-integration/microsoft-azure-reporting?v=24.1#implement-custom-storages" target="_blank" rel="noopener">Documentation: Microsoft Azure Reporting - Implement Custom Storages</a>
</p>
<p> NuGet Packages: <a href="https://nuget.devexpress.com/packages/DevExpress.Web.Reporting.Azure" target="_blank" rel="noopener">ASP.NET Web Forms & MVC</a> |
<a href="https://nuget.devexpress.com/packages/DevExpress.AspNetCore.Reporting.Azure" target="_blank" rel="noopener">ASP.NET Core</a></p> <span class="H-Separator"></span>
<h3 data-anchor="reporting-accessibility" data-toc-title="Accessibility">
<a name="reporting-accessibility" class="anchor"></a>Accessibility
</h3>
<p> We now support assistive tools for the following controls: </p>
<ul>
<li>Native Blazor Report Viewer</li>
<li>JS Report Viewer</li>
<li>WinForms Report Viewer*</li>
<li>WPF Report Viewer*</li>
</ul>
<p><span class="FootNote"> * We are aware of issues and plan to address them in upcoming releases. </span></p>
<p> We have enhanced the accessibility tree to ensure that assistive technologies receive the information they require from user interface elements in accordance with accessibility guidelines outlined in WCAG. </p>
<p> Assistive technologies (screen readers) can now access document content in all the controls listed above. </p>
<p> The following controls now fully supports keyboard navigation: </p>
<ul>
<li>Native Blazor Report Viewer</li>
<li>HTML5/JS Report Viewer</li>
</ul>
<p> Users can move through user interface elements and navigate through document content using tab, arrow and special keys. </p>
<p><a href="https://docs.devexpress.com/XtraReports/402561/web-reporting/common-features/web-accessibility?v=24.1" target="_blank" rel="noopener">Documentation</a></p> <span class="H-Separator"></span>
<h3 data-anchor="reporting-datasources" data-toc-title="Data Sources">
<a name="reporting-datasources" class="anchor"></a>Data Sources
</h3>
<h4 anchor="dashboard-sqldatasource">
<a name="dashboard-sqldatasource" class="anchor visible-anchor" href="#dashboard-sqldatasource">#</a>SqlDataSource Wizard — Trust Level Certificate and Encryption Options
</h4>
<div class="Attention">
<p> Please note that the changes described below are already available in the latest update of our current major version: <strong>v23.2.5</strong>. </p>
</div>
<p> We enhanced the user experience in our
<a href="https://docs.devexpress.com/XtraReports/403142/desktop-reporting/winforms-reporting/end-user-report-designer-for-winforms/gui/data-source-wizard?p=netframework" target="_blank" rel="noopener">Data Source Wizard</a> while
binding a report to an instance of the MS SQL Server. The data source connection screen now features two new options marked on the screenshot: </p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-reporting-sql-data-source-wizard-trustcert-callout.png"
srcset="/subscriptions/i/24.1/24-1-reporting-sql-data-source-wizard-trustcert-callout.png 1x, /subscriptions/i/24.1/24-1-reporting-sql-data-source-wizard-trustcert-callout@2x.png 2x"
alt="SqlDataSource Wizard — Trust Level Certificate and Encryption Options" width="820" height="511" style="border: none" id="ctl00_ctl00_Content_Content_ctl5791"></div>
<p> These new options/changes allow you to avoid the "<strong>The certificate chain was issued by an authority that is not trusted</strong>" error while binding a report to MS SQL Server database if you cannot set up MS SQL Server
differently. Learn more about this error and its cause in the following Microsoft topic:
<a href="https://learn.microsoft.com/en-us/troubleshoot/sql/database-engine/connect/certificate-chain-not-trusted?tabs=ole-db-driver-19" target="_blank" rel="noopener">The certificate chain was issued by an authority that isn't trusted - SQL Server (Microsoft Learn)</a>.
</p>
<p><a href="https://docs.devexpress.com/CoreLibraries/DevExpress.DataAccess.ConnectionParameters.MsSqlConnectionParameters?v=24.1" target="_blank" rel="noopener">New API Members in Documentation</a> |
<a href="https://docs.devexpress.com/XtraReports/2554/detailed-guide-to-devexpress-reporting/bind-reports-to-data/sql-database/bind-a-report-to-a-database?v=24.1" target="_blank" rel="noopener">Reporting — Tutorial</a></p> <span
class="H-Separator"></span>
<h4 anchor="dashboard-postgres-v7">
<a name="dashboard-postgres-v7" class="anchor visible-anchor" href="#dashboard-postgres-v7">#</a>SqlDataSource — Postgres Data Driver v7.0 Support
</h4>
<p> Initially, we hoped to introduce <a href="https://www.postgresql.org/docs/current/sql-createprocedure.html" target="_blank" rel="noopener">Postgres Stored Procedure</a> support, but discovered that they are mostly useful for update
and delete database operations (the <code data-renderer="hljs" class="csharp" data-control="Code-Inline">SqlDataSource</code> component operates in read-only mode). </p>
<p> Instead, we modified our Postgres Database connection and now allow you to bind DevExpress Reports and BI Dashboards to
<a href="https://www.postgresql.org/docs/current/sql-createfunction.html" target="_blank" rel="noopener">Postgres Functions</a> while using the newest v7.0 database driver. </p> <span class="H-Separator"></span>
<h4 anchor="dashboard-jsondatasource">
<a name="dashboard-jsondatasource" class="anchor visible-anchor" href="#dashboard-jsondatasource">#</a>JsonDataSource — The Use of The System.Text.Json NuGet Package
</h4>
<p> With v24.1, DevExpress Reports and BI Dashboard will utilize functionality from the <code data-renderer="hljs" class="csharp" data-control="Code-Inline">System.Text.Json</code> assembly/NuGet package (by default). This change was
influenced by security considerations and the improved performance offered by Microsoft's built-in library. This package is part of .NET, and this change only pertains to the .NET product line; .NET Framework-based products remain
untouched and will continue to use functionality from the <code data-renderer="hljs" class="csharp" data-control="Code-Inline">Newtonsoft.Json</code> package. </p>
<p> If, for any reason, you are unable to utilize System.Text.Json functionality in your .NET-based application, you can set the <code data-renderer="hljs" class="csharp"
data-control="Code-Inline">DevExpress.DataAccess.Native.Json.JsonLoaderHelper.JsonProcessingLibrary</code>* property to <code data-renderer="hljs" class="csharp" data-control="Code-Inline">NewtonsoftJson</code> and continue using the
Newtonsoft.Json library. </p>
<p><span class="FootNote"> * <strong>Note</strong>: We provide this property for backward compatibility purposes. It will be removed from source code in future releases once our migration is complete.<br>We also encourage you to update
your applications accordingly. </span></p> <p><strong>Breaking Change Description</strong>:
<a href="https://supportcenter.devexpress.com/ticket/details/t1224045/system-text-json-is-used-to-process-the-jsondatasource-dashboardjsondatasource-component" target="_blank" rel="noopener">System.Text.Json is used to process the JsonDataSource (DashboardJsonDataSource) component instead of the Newtonsoft.Json library</a>
</p> <span class="H-Separator"></span>
<h3 data-anchor="reporting-survey" data-toc-title="Survey - Reporting">
<a name="reporting-survey" class="anchor"></a>Survey - Reporting
</h3>
<h4 anchor=""> Your Feedback Matters! </h4>
<div id="ctl00_ctl00_Content_Content_SurveyContainer" data-control="survey" class="InlineSurvey">
<div data-role="SurveyContent" data-markdown="false" data-partial="false" data-multiple-results="None" data-survey-id="8af3dee0-0fe5-4fcd-9df3-bca805963cc9" data-auth-required="true"
data-user-data="{"IsLoggedIn":false,"IsEmployee":false,"CustomerId":null}" style="display: none;">
</div>
<div data-role="AuthRequired" style="display: block;"> Please <a href="https://www.devexpress.com/MyAccount/LogIn/?returnUrl=https%3a%2f%2fwww.devexpress.com%2fsubscriptions%2fwhats-new%2f">login</a> to complete the survey. </div>
<div data-role="Loading" style="display: none;">
<img src="../../Content/Editors/ajax-loader.gif" style="border-width:0px;">
</div>
<div data-role="Completed" style="display: none;">
<h3> Survey Completed </h3>
<p class="sys-max-width-md-80 sys-max-width-lg-60">Thank you for taking the time to complete this survey. Your responses have now been posted. If you want to follow up with additional information, feel free to send us an email at
<a href="mailto:clientservices@devexpress.com">clientservices@devexpress.com</a> anytime. </p>
</div>
<div data-role="AlreadyPassed" style="display: none;">
<h3> You've Already Completed This Survey </h3>
<p class="sys-max-width-md-80 sys-max-width-lg-60">Our records show that you have already completed this survey. If you want to follow up with additional information, send us an email at
<a href="mailto:clientservices@devexpress.com">clientservices@devexpress.com</a>.</p>
</div>
<div data-role="Expired" style="display: none;">
<h3> This survey has expired </h3>
<p>If you want to share your feedback or request new functionality, please submit a new support ticket via the <a href="https://supportcenter.devexpress.com/">DevExpress Support Center</a>. We’ll be happy to follow up.</p>
</div>
</div>
<h2 class="SectionHeader" data-anchor="dashboard" data-toc-title="BI Dashboard">
<a data-whatsnew-platform="dashboard" name="dashboard" class="anchor"></a>Business Intelligence Dashboard v24.1
</h2>
<h4 anchor="">
</h4>
<ul>
<li><a href="#dashboard-cascading-parameters">Cascading Parameters</a></li>
<li><a href="#web-dashboard">Web Dashboard Enhancements</a></li>
<li><a href="#dashboard-data-sources">Data Sources</a></li>
</ul>
<h3 data-anchor="dashboard-cascading-parameters" data-toc-title="Cascading Parameters">
<a name="dashboard-cascading-parameters" class="anchor"></a>Cascading Parameters
</h3>
<p> You can now set up cascading parameters to filter the data source or items in a dashboard. The list of values of a dependent parameter now refreshes automatically when you change the value of the parent parameter. When using two
parameters, the parent parameter is used to filter the data source for the dependent parameter with dynamic list settings. The following image illustrates cascading parameters where Products parameter values are filtered by the selected
Category: </p> <p><span class="NativeVideo"><span><video style="width:1000px;" preload="auto">
<source src="/subscriptions/i/24.1/24-1-dashboard-cascading-parameters.mp4" type="video/mp4">
</video></span></span></p> <p>
<a href="https://docs.devexpress.com/Dashboard/404884/winforms-dashboard/winforms-designer/create-dashboards-in-the-winforms-designer/data-analysis/dashboard-parameters/create-cascading-parameters?v=24.1" target="_blank" rel="noopener">Documentation (WinForms)</a>
| <a href="https://docs.devexpress.com/Dashboard/404895/web-dashboard/create-dashboards-on-the-web/data-analysis/dashboard-parameters/cascading-parameters?v=24.1" target="_blank" rel="noopener">Documentation (Web)</a></p> <span
class="H-Separator"></span>
<h3 data-anchor="web-dashboard" data-toc-title="Web Dashboard Enhancements">
<a name="web-dashboard" class="anchor"></a>Web Dashboard Enhancements
</h3>
<h4 anchor="web-dashboard-cache-api">
<a name="web-dashboard-cache-api" class="anchor visible-anchor" href="#web-dashboard-cache-api">#</a>Cache Management API
</h4>
<p> This update allows you to tailor our built-in BI Dashboard caching engine. Customers encountered several scenarios where our built-in cache needed to be disabled, prompting us to introduce the following API. </p>
<p> You can now use the <a href="https://docs.devexpress.com/Dashboard/DevExpress.DashboardWeb.ASPxDashboard.DataSourceCacheEnabled?v=24.1" target="_blank" rel="noopener">ASPxDashboard.DataSourceCacheEnabled</a> property for Web Forms (or
the <a href="https://docs.devexpress.com/Dashboard/DevExpress.DashboardWeb.DashboardConfigurator.DataSourceCacheEnabled?v=24.1" target="_blank" rel="noopener">DashboardConfigurator.DataSourceCacheEnabled</a> property for other web
platforms) to disable caching entirely. This forces the DevExpress Dashboard to load the most relevant data whenever a user accesses and views a dashboard. </p>
<p> By default, whenever a dashboard parameter value changes, a new data source instance is created and stored in the cache. This impacts memory usage, especially when a parameter doesn't affect data source filtering. As such, we added
the <a href="https://docs.devexpress.com/Dashboard/DevExpress.DashboardWeb.ASPxDashboard.DataSourceCacheKeyCreated?v=24.1" target="_blank" rel="noopener">ASPxDashboard.DataSourceCacheKeyCreated</a>/
<a href="https://docs.devexpress.com/Dashboard/DevExpress.DashboardWeb.DashboardConfigurator.DataSourceCacheKeyCreated?v=24.1" target="_blank" rel="noopener">DashboardConfigurator.DataSourceCacheKeyCreated</a> event to prevent the
creation of new cache records based on parameter values/available event arguments. For instance, consider the following: </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">C#</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="csharp">DashboardConfigurator.Default.DataSourceCacheKeyCreated += (s, e) => {
<span class="hljs-keyword">if</span>(e.Key.DashboardId == <span class="hljs-string">"MyDashboard"</span>)
e.Key.Parameters.Clear();
};</code></pre>
</div>
</div>
<p> In this scenario, altering a parameter value updates dashboard item data, while reusing the existing data source from the cache without additional fill requests. </p>
<p> Furthermore, you can utilize this event to update a specific data source when any interaction with the dashboard takes place: </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">C#</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="csharp">DashboardConfigurator.Default.DataSourceCacheKeyCreated += (s, e) => {
<span class="hljs-keyword">if</span>(e.Key.DataSourceId == <span class="hljs-string">"dsSales"</span>)
e.InvalidateCacheRecord();
};</code></pre>
</div>
</div>
<p> Another use case involves increasing cache key granularity by including groups of users or the users themselves in the cache key. You can utilize the new
<a href="https://docs.devexpress.com/Dashboard/DevExpress.DashboardCommon.IDataSourceCacheKey.CustomData?v=24.1" target="_blank" rel="noopener">IDataSourceCacheKey.CustomData</a> property for this purpose. The primary advantage of this
strategy is that the key is solely used for creating/retrieving records from the cache and is never exposed on the client side, thus maintaining the security aspect of the implementation: </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">C#</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="csharp">DashboardConfigurator.Default.DataSourceCacheKeyCreated += (s, e) => {
e.Key.CustomData.Add(<span class="hljs-string">"UserId"</span>, CurrentUser.UserId);
};</code></pre>
</div>
</div> <span class="H-Separator"></span>
<h4 anchor="web-dashboard-keyboard-nav">
<a name="web-dashboard-keyboard-nav" class="anchor visible-anchor" href="#web-dashboard-keyboard-nav">#</a>Accessibility — Keyboard Navigation
</h4>
<p> Keyboard navigation is fully supported for groups and dashboard items. Users can move through user interface elements using tab, arrow and special keys. </p> <span class="H-Separator"></span>
<h3 data-anchor="dashboard-data-sources" data-toc-title="Data Sources">
<a name="dashboard-data-sources" class="anchor"></a>Data Sources
</h3>
<h4 anchor="dashboard-sqldatasource">
<a name="dashboard-sqldatasource" class="anchor visible-anchor" href="#dashboard-sqldatasource">#</a>SqlDataSource Wizard — Trust Level Certificate and Encryption Options
</h4>
<div class="Attention">
<p class="sys-h-align-left"> Please note that the changes described below are already available in the latest update of our current major version: <strong>v23.2.5</strong>. </p>
</div>
<p> We enhanced the user experience in our
<a href="https://docs.devexpress.com/XtraReports/403142/desktop-reporting/winforms-reporting/end-user-report-designer-for-winforms/gui/data-source-wizard" target="_blank" rel="noopener">Data Source Wizard</a> while binding a report to
an instance of the MS SQL Server. The data source connection screen now features two new options marked on the screenshot: </p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-reporting-sql-data-source-wizard-trustcert-callout.png"
srcset="/subscriptions/i/24.1/24-1-reporting-sql-data-source-wizard-trustcert-callout.png 1x, /subscriptions/i/24.1/24-1-reporting-sql-data-source-wizard-trustcert-callout@2x.png 2x"
alt="SqlDataSource Wizard — Trust Level Certificate and Encryption Options" width="820" height="511" style="border: none" id="ctl00_ctl00_Content_Content_ctl6152"></div>
<p> These new options/changes allow you to avoid the "<strong>The certificate chain was issued by an authority that is not trusted</strong>" error while binding a report to MS SQL Server database if you cannot set up MS SQL Server
differently. Learn more about this error and its cause in the following Microsoft topic:
<a href="https://learn.microsoft.com/en-us/troubleshoot/sql/database-engine/connect/certificate-chain-not-trusted?tabs=ole-db-driver-19" target="_blank" rel="noopener">The certificate chain was issued by an authority that isn't trusted - SQL Server (Microsoft Learn)</a>.
</p>
<p><a href="https://docs.devexpress.com/CoreLibraries/DevExpress.DataAccess.ConnectionParameters.MsSqlConnectionParameters?v=24.1" target="_blank" rel="noopener">New API Members in Documentation</a> |
<a href="https://docs.devexpress.com/Dashboard/16065/winforms-dashboard/winforms-designer/create-dashboards-in-the-winforms-designer/providing-data/sql-data-source/connect-to-sql-databases/microsoft-sql-server?v=24.1" target="_blank" rel="noopener">BI Dashboard — Tutorial</a>
</p> <span class="H-Separator"></span>
<h4 anchor="dashboard-postgres-v7">
<a name="dashboard-postgres-v7" class="anchor visible-anchor" href="#dashboard-postgres-v7">#</a>SqlDataSource — Postgres Data Driver v7.0 Support
</h4>
<p> Initially, we hoped to introduce <a href="https://www.postgresql.org/docs/current/sql-createprocedure.html" target="_blank" rel="noopener">Postgres Stored Procedure</a> support, but discovered that they are mostly useful for update
and delete database operations (the <code data-control="Code" class="Code Inline"><code class=" language-cs">SqlDataSource</code></code> component operates in read-only mode). </p>
<p> Instead, we modified our Postgres Database connection and now allow you to bind DevExpress Reports and BI Dashboards to
<a href="https://www.postgresql.org/docs/current/sql-createfunction.html" target="_blank" rel="noopener">Postgres Functions</a> while using the newest v7.0 database driver. </p> <span class="H-Separator"></span>
<h4 anchor="dashboard-jsondatasource">
<a name="dashboard-jsondatasource" class="anchor visible-anchor" href="#dashboard-jsondatasource">#</a>JsonDataSource — The Use of The System.Text.Json NuGet Package
</h4>
<p> With v24.1, DevExpress Reports and BI Dashboard will utilize functionality from the <code data-control="Code" class="Code Inline"><code class=" language-cs">System<span class="token punctuation">.</span>Text<span
class="token punctuation">.</span>Json</code></code> assembly/NuGet package (by default). This change was influenced by security considerations and the improved performance offered by Microsoft's built-in library. This package is
part of .NET, and this change only pertains to the .NET product line; .NET Framework-based products remain untouched and will continue to use functionality from the <code data-control="Code" class="Code Inline"><code
class=" language-cs">Newtonsoft<span class="token punctuation">.</span>Json</code></code> package. </p>
<p> If, for any reason, you are unable to utilize System.Text.Json functionality in your .NET-based application, you can set the <code data-control="Code" class="Code Inline"><code class=" language-cs">DevExpress<span
class="token punctuation">.</span>DataAccess<span class="token punctuation">.</span>Native<span class="token punctuation">.</span>Json<span class="token punctuation">.</span>JsonLoaderHelper<span
class="token punctuation">.</span>JsonProcessingLibrary</code></code>* property to <code data-control="Code" class="Code Inline"><code class=" language-cs">NewtonsoftJson</code></code> and continue using the Newtonsoft.Json
library. </p>
<p><span class="FootNote"> * <strong>Note</strong>: We provide this property for backward compatibility purposes. It will be removed from source code in future releases once our migration is complete.<br>We also encourage you to update
your applications accordingly. </span></p> <p><strong>Breaking Change Description</strong>:
<a href="https://supportcenter.devexpress.com/ticket/details/t1224045/system-text-json-is-used-to-process-the-jsondatasource-dashboardjsondatasource-component" target="_blank" rel="noopener">System.Text.Json is used to process the JsonDataSource (DashboardJsonDataSource) component instead of the Newtonsoft.Json library</a>
</p> <span class="H-Separator"></span>
<h2 class="SectionHeader" data-anchor="officefileapi" data-toc-title="Office File API">
<a data-whatsnew-platform="officefileapi" name="officefileapi" class="anchor"></a>Office File API v24.1
</h2>
<div class="Attention">
<p><strong>Your feedback matters.</strong><br> Please, review the description of <strong>DevExpress Office File API</strong>-related features below and leave your feedback at the end of the section. </p>
<p><a href="#officefileapi-survey">Go to the survey now.</a></p>
</div>
<h3 data-anchor="ofa-accessibility" data-toc-title="Accessibility Enhancements">
<a name="ofa-accessibility" class="anchor"></a>Accessibility Enhancements
</h3>
<p> We extended accessibility-related support to the following elements when exporting Word documents to accessible PDF files: </p>
<ul>
<li>Table of Contents tagging</li>
<li>Metadata fields</li>
<li>Alt text handling</li>
<li>Tables</li>
<li>Floating objects</li>
</ul>
<p> Adobe Acrobat Pro and PDF Accessibility Checker 2024 were used for quality control. Our test documents successfully passed validation for PDF/UA compatibility and WCAG 2.1 compliance. </p>
<p> Accessibility-related export enhancements are available out-of-the-box when you specify the <code data-control="Code" class="Code Inline"><code class=" language-cs">PdfUACompatibility</code></code> option: </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">C#</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="csharp"><span class="hljs-keyword">using</span> System.IO;
<span class="hljs-keyword">using</span> DevExpress.XtraRichEdit;
<span class="hljs-comment">// ...</span>
RichEditDocumentServer wordProcessor = <span class="hljs-keyword">new</span> RichEditDocumentServer();
<span class="hljs-comment">//...</span>
<span class="hljs-keyword">using</span>(FileStream stream =
<span class="hljs-keyword">new</span> FileStream(resultFilePath, FileMode.Create, FileAccess.Write, FileShare.Read)) {
PdfExportOptions exportOptions = <span class="hljs-keyword">new</span> PdfExportOptions();
exportOptions.PdfUACompatibility = PdfUACompatibility.PdfUA1;
wordProcessor.ExportToPdf(stream, exportOptions);
}</code></pre>
</div>
</div>
<p> In addition, we added a <code data-control="Code" class="Code Inline"><code class=" language-cs">Decorative</code></code> property for both
<a href="https://docs.devexpress.com/OfficeFileAPI/DevExpress.XtraRichEdit.API.Native.DrawingObject.Decorative?v=24.1" target="_blank" rel="noopener">Word Processing Shape</a> and
<a href="https://docs.devexpress.com/OfficeFileAPI/DevExpress.Spreadsheet.Shape.Decorative?v=24.1" target="_blank" rel="noopener">Spreadsheet Shape</a> classes to mark document graphics (pictures, shapes, and charts) as decorative.
Decorative shapes add visual interest, but they are not informative. Thus, you do not need to specify Alt Text (meaningful description) for decorative objects when you generate an accessible document. </p> <span
class="H-Separator"></span>
<h3 data-anchor="ofa-unix-printing" data-toc-title="Printing on Unix-based Systems">
<a name="ofa-unix-printing" class="anchor"></a>Printing on Unix-based Systems
</h3>
<p> In this release (v24.1), we added printing support for .NET-based Office File API powered applications running on Unix-based systems. You can now print barcodes, and Word, Excel, and PDF documents in non-Windows environments. </p>
<p> We created a new set of APIs that work with the <a href="https://docs.devexpress.com/CoreLibraries/DevExpress.Drawing.Printing.DXPrinterSettings" target="_blank" rel="noopener">DXPrinterSettings</a> options available in our
<a href="https://docs.devexpress.com/CoreLibraries/404247/devexpress-drawing-library" target="_blank" rel="noopener">DevExpress.Drawing</a> library. </p>
<p> Use the following new methods to print your documents and barcodes on Unix-based systems: </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">C#</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="csharp"><span class="hljs-comment">// DevExpress.XtraRichEdit.RichEditDocumentServer: </span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">Print</span>(<span class="hljs-params">DXPrinterSettings printerSettings, <span class="hljs-built_in">string</span> printDocumentName</span>)</span>;
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">Print</span>(<span class="hljs-params">DXPrinterSettings printerSettings</span>)</span>;
<span class="hljs-comment">//DevExpress.Spreadsheet.Workbook: </span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">Print</span>(<span class="hljs-params">DXPrinterSettings printerSettings</span>)</span>;
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">Print</span>(<span class="hljs-params">DXPrinterSettings printerSettings, <span class="hljs-keyword">params</span> <span class="hljs-built_in">string</span>[] sheetNames</span>)</span>;
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">Print</span>(<span class="hljs-params">DXPrinterSettings printerSettings, IEnumerable<<span class="hljs-built_in">string</span>> sheetNames</span>)</span>;
<span class="hljs-comment">//DevExpress.BarCodes.BarCode: </span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">Print</span>(<span class="hljs-params">DXPrinterSettings printerSettings</span>)</span>;</code></pre>
</div>
</div>
<p> For the <code data-control="Code" class="Code Inline"><code class=" language-cs">DevExpress<span class="token punctuation">.</span>Pdf<span class="token punctuation">.</span>PdfDocumentProcessor</code></code> class, you still need to
call the current <code data-control="Code" class="Code Inline"><code class=" language-cs"><span class="token function">Print</span><span class="token punctuation">(</span><span class="token class-name">PdfPrinterSettings</span>
printerSettings<span class="token punctuation">)</span></code></code> method. To modify print settings, use the new <code data-control="Code" class="Code Inline"><code class=" language-cs">PdfPrinterSettings<span
class="token punctuation">.</span>DXPrinterSettings</code></code> option as follows: </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">C#</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="csharp"><span class="hljs-keyword">using</span> DevExpress.Drawing.Printing;
<span class="hljs-keyword">using</span> DevExpress.Pdf;
<span class="hljs-comment">// Load a PDF file</span>
PdfDocumentProcessor documentProcessor = <span class="hljs-keyword">new</span> PdfDocumentProcessor();
documentProcessor.LoadDocument(<span class="hljs-string">@"..\..\Demo.pdf"</span>);
<span class="hljs-comment">// Declare printer settings</span>
PdfPrinterSettings pdfPrinterSettings = <span class="hljs-keyword">new</span> PdfPrinterSettings();
<span class="hljs-comment">// Specify CUPS printer settings</span>
DXPrinterSettings dxPrinterSettings = pdfPrinterSettings.DXSettings;
dxPrinterSettings.Duplex = DXDuplexMode.DuplexLongEdge;
dxPrinterSettings.Copies = <span class="hljs-number">3</span>;
<span class="hljs-comment">// Print the document</span>
documentProcessor.Print(pdfPrinterSettings);</code></pre>
</div>
</div>
<p><strong>Note</strong>: For Unix-based systems, you need to install the <code data-control="Code" class="Code Inline"><code class=" language-cs">libcups2</code></code> package separately. </p> <span class="H-Separator"></span>
<h3 data-anchor="ofa-export-to-svg" data-toc-title="Export Documents to SVG">
<a name="ofa-export-to-svg" class="anchor"></a>Export Documents to SVG
</h3>
<p> We extended our image export engine and now support SVG images within our Barcode Generation API, Word Processing Document API, and Spreadsheet Document API libraries. With v24.1, you can generate SVG images from your Barcodes, Word
document pages and Excel worksheets/cell ranges in both Windows and non-Windows environments. </p>
<p> To generate an SVG image from a barcode, create a BarCode class instance, modify settings as necessary and call the
<a href="https://docs.devexpress.com/OfficeFileAPI/DevExpress.BarCodes.BarCode.Save(System.String-DevExpress.Drawing.DXImageFormat)?v=24.1" target="_blank" rel="noopener">BarCode.Save</a> method with <code data-control="Code"
class="Code Inline"><code class=" language-cs">DXImageFormat<span class="token punctuation">.</span>Svg</code></code> as a parameter. </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">C#</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="csharp"><span class="hljs-keyword">using</span> (BarCode barCode = <span class="hljs-keyword">new</span> BarCode()) {
barCode.Symbology = Symbology.QRCode;
barCode.BackColor = Color.White;
barCode.ForeColor = Color.Black;
barCode.RotationAngle = <span class="hljs-number">0</span>;
barCode.CodeBinaryData = Encoding.Default.GetBytes(<span class="hljs-string">"https://www.devexpress.com/"</span>);
barCode.Options.QRCode.CompactionMode = QRCodeCompactionMode.Byte;
barCode.Options.QRCode.ErrorLevel = QRCodeErrorLevel.Q;
barCode.Options.QRCode.ShowCodeText = <span class="hljs-literal">false</span>;
barCode.DpiX = <span class="hljs-number">72</span>;
barCode.DpiY = <span class="hljs-number">72</span>;
barCode.Module = <span class="hljs-number">2f</span>;
barCode.Save(<span class="hljs-string">"barcode.svg"</span>, DXImageFormat.Svg);
}</code></pre>
</div>
</div>
<p> For Word documents, use our new Image Export API - create an <code data-control="Code" class="Code Inline"><code class=" language-cs">RichEditImageExportOptions</code></code> instance, specify the target DXImageFormat.Svg format
using the <code data-control="Code" class="Code Inline"><code class=" language-cs">RichEditImageExportOptions<span class="token punctuation">.</span>Format</code></code> property and call the
<a href="https://docs.devexpress.com/OfficeFileAPI/DevExpress.XtraRichEdit.RichEditDocumentServerExtensions.ExportToImage.overloads?v=24.1" target="_blank" rel="noopener">RichEditDocumentServerExtensions.ExportToImage</a> extension
method with the RichEditImageExportOptions object as a parameter. </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">C#</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="csharp"><span class="hljs-keyword">using</span> (<span class="hljs-keyword">var</span> wordProcessor = <span class="hljs-keyword">new</span> RichEditDocumentServer()) {
wordProcessor.LoadDocument(<span class="hljs-string">@"C:\Documents\Alice.docx"</span>);
RichEditImageExportOptions options = <span class="hljs-keyword">new</span> RichEditImageExportOptions();
options.Format = DXImageFormat.Svg;
options.PageRange = <span class="hljs-string">"1"</span>;
wordProcessor.Document.ExportToImage(<span class="hljs-string">"first_page_image.svg"</span>, options);
}</code></pre>
</div>
</div>
<p> To export a cell range in an Excel worksheet to an SVG image, call the
<a href="https://docs.devexpress.com/OfficeFileAPI/DevExpress.Spreadsheet.CellRangeExtensions.ExportToImage.overloads?v=24.1" target="_blank" rel="noopener">CellRangeExtensions.ExportToImage</a> method with <code data-control="Code"
class="Code Inline"><code class=" language-cs">ImageFileFormat<span class="token punctuation">.</span>Svg</code></code> as a parameter. </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">C#</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="csharp"><span class="hljs-keyword">using</span> (Workbook workbook = <span class="hljs-keyword">new</span> Workbook()) {
workbook.LoadDocument(<span class="hljs-string">"InvestmentPortfolio.xlsx"</span>, DevExpress.Spreadsheet.DocumentFormat.Xlsx);
Worksheet worksheet = workbook.Worksheets.ActiveWorksheet;
worksheet.Range[<span class="hljs-string">"B18:I30"</span>].ExportToImage(<span class="hljs-string">"cell_range_image.svg"</span>, ImageFileFormat.Svg);
}</code></pre>
</div>
</div> <span class="H-Separator"></span>
<h3 data-anchor="ofa-spreadsheet-api" data-toc-title="Spreadsheet Document API">
<a name="ofa-spreadsheet-api" class="anchor"></a>Spreadsheet Document API
</h3>
<h4 anchor="ofa-spreadsheet-api-text-align">
<a name="ofa-spreadsheet-api-text-align" class="anchor visible-anchor" href="#ofa-spreadsheet-api-text-align">#</a>Justify & Distributed Text Alignment
</h4>
<p> v24.1 adds support for <strong>Justify</strong> and <strong>Distributed</strong> horizontal alignment types within Spreadsheet cells. Excel files using these alignment options can be printed and exported to PDF. </p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-ofa-spreadsheet-document-api-justify-and-distributed-text-align.png"
srcset="/subscriptions/i/24.1/24-1-ofa-spreadsheet-document-api-justify-and-distributed-text-align.png 1x, /subscriptions/i/24.1/24-1-ofa-spreadsheet-document-api-justify-and-distributed-text-align@2x.png 2x"
alt="Justify and Distributed Text Alignment, Spreadsheet Document API | DevExpress" width="515" height="327" style="border: none" id="ctl00_ctl00_Content_Content_ctl6378"></div>
<p> You can use the <a href="https://docs.devexpress.com/OfficeFileAPI/DevExpress.Spreadsheet.Alignment.Horizontal" target="_blank" rel="noopener">Cell.Alignment.Horizontal</a> property to specify horizontal alignment in code. </p>
<p> The following code snippet specifies alignment in code: </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">C#</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="csharp"><span class="hljs-keyword">var</span> workbook = <span class="hljs-keyword">new</span> Workbook();
<span class="hljs-keyword">var</span> worksheet = workbook.Worksheets[<span class="hljs-number">0</span>];
Cell cellA1 = worksheet.Cells[<span class="hljs-string">"A1"</span>];
cellA1.Value = <span class="hljs-string">"Justified and top"</span>;
cellA1.Alignment.Horizontal = SpreadsheetHorizontalAlignment.Justify;
cellA1.Alignment.Vertical = SpreadsheetVerticalAlignment.Top;
workbook.ExportToPdf(<span class="hljs-string">"Result.pdf"</span>);</code></pre>
</div>
</div> <span class="H-Separator"></span>
<h4 anchor="ofa-spreadsheet-api-sort-filter-by-color">
<a name="ofa-spreadsheet-api-sort-filter-by-color" class="anchor visible-anchor" href="#ofa-spreadsheet-api-sort-filter-by-color">#</a>Sort and Filter by Color
</h4>
<p> The DevExpress Spreadsheet Document API ships with enhanced filter and sort-related capabilities. We added new APIs that can sort and filter workbook data by background and font color. Cell ranges filtered/sorted by cell color can be
also printed and exported to PDF. </p>
<p> Our Sorting APIs include new <a href="https://docs.devexpress.com/OfficeFileAPI/DevExpress.Spreadsheet.Worksheet.Sort.overloads?v=24.1" target="_blank" rel="noopener">Worksheet.Sort</a> method overloads designed to sort a specified
range by font color or fill setting (background color and pattern). </p>
<p> The following code snippet sorts cell values across two cell ranges - the first is sorted by a red font color and the second is sorted by fill settings specified for the first cell in the range: </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">C#</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="csharp">workbook.LoadDocument(<span class="hljs-string">"sort-filter.xlsx"</span>);
Worksheet worksheet = workbook.Worksheets.ActiveWorksheet;
<span class="hljs-comment">// Sort cell range by font color </span>
worksheet.Sort(worksheet[<span class="hljs-string">"B2:B10"</span>], Color.Red);
<span class="hljs-comment">// Sort cell range by fill color</span>
worksheet.Sort(worksheet[<span class="hljs-string">"D2:D10"</span>], worksheet[<span class="hljs-string">"D2"</span>].Fill);</code></pre>
</div>
</div>
<p> To filter cells by font or background color, you need to apply an auto-filter to the required cell range or table. Once complete, you need to obtain the required column from the <code data-control="Code" class="Code Inline"><code
class=" language-cs">AutoFilter<span class="token punctuation">.</span>Columns</code></code> collection and call one of the following methods: </p>
<ul>
<li><a href="https://docs.devexpress.com/OfficeFileAPI/DevExpress.Spreadsheet.AutoFilterColumn.ApplyFillColorFilter(System.Drawing.Color)?v=24.1" target="_blank" rel="noopener">AutoFilterColumn.ApplyFillColorFilter(Color)</a></li>
<li><a href="https://docs.devexpress.com/OfficeFileAPI/DevExpress.Spreadsheet.AutoFilterColumn.ApplyFillFilter(DevExpress.Spreadsheet.Fill)?v=24.1" target="_blank" rel="noopener">AutoFilterColumn.ApplyFillFilter(Fill)</a></li>
<li><a href="https://docs.devexpress.com/OfficeFileAPI/DevExpress.Spreadsheet.AutoFilterColumn.ApplyFontColorFilter(System.Drawing.Color)?v=24.1" target="_blank" rel="noopener">AutoFilterColumn.ApplyFontColorFilter(Color)</a></li>
</ul>
<p> The following code snippet uses these methods for both cell range and table: </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">C#</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="csharp">workbook.LoadDocument(<span class="hljs-string">"sort-filter.xlsx"</span>);
Worksheet worksheet = workbook.Worksheets.ActiveWorksheet;
<span class="hljs-comment">// Apply an auto-filter to a cell range and filter the first column by font color</span>
worksheet.AutoFilter.Apply(worksheet[<span class="hljs-string">"B1:B10"</span>]);
worksheet.AutoFilter.Columns[<span class="hljs-number">0</span>].ApplyFontColorFilter(Color.Red);
<span class="hljs-comment">// Create a table, apply an auto-filter and filter the first column by fill color</span>
Table table = worksheet.Tables.Add(worksheet[<span class="hljs-string">"B12:B21"</span>], <span class="hljs-literal">true</span>);
table.AutoFilter.Apply();
table.AutoFilter.Columns[<span class="hljs-number">0</span>].ApplyFillColorFilter(Color.Red);</code></pre>
</div>
</div>
<p> In addition, our new APIs allow you to sort data across a filtered range (when auto-filter is enabled) and sort cells by their values/colors simultaneously (using sorting conditions). </p>
<p><a href="https://docs.devexpress.com/OfficeFileAPI/113728/spreadsheet-document-api/examples/sorting?v=24.1#sort-range-by-color" target="_blank" rel="noopener">Documentation: Sort Cell Range by Color</a></p> <span
class="H-Separator"></span>
<h3 data-anchor="ofa-pdf-api" data-toc-title="PDF Document API">
<a name="ofa-pdf-api" class="anchor"></a>PDF Document API
</h3>
<h4 anchor="ofa-pdf-api-layers">
<a name="ofa-pdf-api-layers" class="anchor visible-anchor" href="#ofa-pdf-api-layers">#</a>Layers API
</h4>
<p> v24.1 includes an enhanced PDF Facade API and new APIs designed to manage Optional Content (Layers) visibility in code. </p>
<p><strong>Note</strong>: A PDF document only stores a default Optional Content configuration. This means that Layer visibility is not preserved when you save the document. Visibility settings are only applicable when you preview the
document in the PDF Viewer component or print the document/export it to an image. </p>
<p> The new API is available via the <a href="https://docs.devexpress.com/OfficeFileAPI/DevExpress.Pdf.PdfDocumentFacade.OptionalContentVisibility?v=24.1" target="_blank" rel="noopener">PdfDocumentFacade.OptionalContentVisibility</a>
property. Access Optional Content groups using the <code data-control="Code" class="Code Inline"><code class=" language-cs">PdfOptionalContentVisibility<span class="token punctuation">.</span>Groups</code></code> collection. To change
group visibility, modify the <a href="https://docs.devexpress.com/OfficeFileAPI/DevExpress.Pdf.PdfOptionalContentGroupVisibility.Visible?v=24.1" target="_blank" rel="noopener">PdfOptionalContentGroupVisibility.Visible</a> property
value. </p>
<p> The following code snippet changes visibility for Optional Content groups stored in the document and generates print/image output (to preview results): </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">C#</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="csharp">PdfDocumentProcessor processor = <span class="hljs-keyword">new</span> PdfDocumentProcessor();
processor.LoadDocument(<span class="hljs-string">"layers.pdf"</span>);
<span class="hljs-comment">// Set visibility for each Layer</span>
processor.DocumentFacade.OptionalContentVisibility.Groups[<span class="hljs-number">0</span>].Visible = <span class="hljs-literal">false</span>;
processor.DocumentFacade.OptionalContentVisibility.Groups[<span class="hljs-number">1</span>].Visible = <span class="hljs-literal">false</span>;
processor.DocumentFacade.OptionalContentVisibility.Groups[<span class="hljs-number">2</span>].Visible = <span class="hljs-literal">true</span>;
<span class="hljs-comment">// Print document or export its page to an image to check the result</span>
DXBitmap bitmap = processor.CreateDXBitmap(<span class="hljs-number">1</span>, <span class="hljs-number">1000</span>);
processor.Print();</code></pre>
</div>
</div>
<p>
<a href="https://docs.devexpress.com/OfficeFileAPI/404880/pdf-document-api/additional-content/manage-optional-content-group-visibility" target="_blank" rel="noopener">Documentation: Manage Visibility of Layers (Optional Content Groups)</a>
</p> <span class="H-Separator"></span>
<h4 anchor="ofa-pdf-api-pdfa-converter">
<a name="ofa-pdf-api-pdfa-converter" class="anchor visible-anchor" href="#ofa-pdf-api-pdfa-converter">#</a>PDF-A Converter Enhancements
</h4>
<p> With this release (v24.1), our <a href="https://docs.devexpress.com/OfficeFileAPI/DevExpress.Pdf.PdfDocumentConverter?v=24.1" target="_blank" rel="noopener">PdfDocumentConverter</a> can convert your documents to PDF/A-1b. To create
PDF/A-1b documents, pass the <code data-control="Code" class="Code Inline"><code class=" language-cs">PdfCompatibility<span class="token punctuation">.</span>PdfA1b</code></code> value to the
<a href="https://docs.devexpress.com/OfficeFileAPI/DevExpress.Pdf.PdfDocumentConverter.Convert(DevExpress.Pdf.PdfCompatibility)?v=24.1" target="_blank" rel="noopener">Convert</a> method as a parameter. </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">C#</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="csharp"><span class="hljs-keyword">using</span> DevExpress.Pdf;
<span class="hljs-comment">// ...</span>
<span class="hljs-keyword">var</span> filePath = <span class="hljs-string">"PdfAConversionDemo.pdf"</span>;
<span class="hljs-keyword">var</span> converter = <span class="hljs-keyword">new</span> PdfDocumentConverter(filePath);
<span class="hljs-comment">// Convert the file to the Pdf/A1-b format.</span>
converter.Convert(PdfCompatibility.PdfA1b);
converter.SaveDocument(<span class="hljs-string">"Result.pdf"</span>);</code></pre>
</div>
</div>
<p> We also added <a href="https://docs.devexpress.com/OfficeFileAPI/DevExpress.Pdf.PdfDocumentConverter.PdfACompatibility?v=24.1" target="_blank" rel="noopener">PdfDocumentConverter.PdfACompatibility</a> and
<a href="https://docs.devexpress.com/OfficeFileAPI/DevExpress.Pdf.PdfDocumentConverter.PdfUACompatibility?v=24.1" target="_blank" rel="noopener">PdfDocumentConverter.PdfUACompatibility</a> properties to help obtain the current PDF/A and
PDF/UA versions of the document loaded to the converter. </p> <span class="H-Separator"></span>
<h3 data-anchor="ofa-word-api" data-toc-title="Word Processing Document API">
<a name="ofa-word-api" class="anchor"></a>Word Processing Document API
</h3>
<h4 anchor="ofa-word-api-math-equations">
<a name="ofa-word-api-math-equations" class="anchor visible-anchor" href="#ofa-word-api-math-equations">#</a>Math Equations
</h4>
<p> Our Word Processing tools now preserve Math Equations when saving a document. You can import your Word documents with Math Equations in our Word Processing Document API library and save them to the RTF and OpenXml (.docx/.docm)
formats without content loss. Note: Math Equations will be printed or exported to PDF only if the source document contains a fallback image for a Math Equation. To suppress Math Equation import, set the
<a href="https://docs.devexpress.com/OfficeFileAPI/DevExpress.XtraRichEdit.DocumentCapabilitiesOptions.MathEquations?v=24.1" target="_blank" rel="noopener">DocumentCapabilities.MathEquations</a> property to <code data-control="Code"
class="Code Inline"><code class=" language-cs">DocumentCapability<span class="token punctuation">.</span>Disabled</code></code>. </p> <span class="H-Separator"></span>
<h4 anchor="ofa-word-api-image-export">
<a name="ofa-word-api-image-export" class="anchor visible-anchor" href="#ofa-word-api-image-export">#</a>Cross-Platform Image Export API
</h4>
<p> v24.1 includes new cross-platform APIs to export Word document pages to an image. This new capability allows you to generate document previews in both Windows and non-Windows environments. With our new APIs, you can convert document
pages to raster and vector images (PNG, JPEG, BMP, multi-page Tiff, emf), save them as physical files on the disk or obtain a list of image streams for further processing in code. You can also set image background color, modify output
image resolution, or generate thumbnail images with a specified size. </p>
<p> The new API is available via the
<a href="https://docs.devexpress.com/OfficeFileAPI/DevExpress.XtraRichEdit.RichEditDocumentServerExtensions.ExportToImage.overloads?v=24.1" target="_blank" rel="noopener">RichEditDocumentServerExtensions.ExportToImage</a> extension
method of the <code data-control="Code" class="Code Inline"><code class=" language-cs">Document</code></code> object. </p>
<div class="Attention">
<p class="sys-h-align-left"> Please note that the <code data-control="Code" class="Code Inline"><code class=" language-cs">RichEditDocumentServerExtensions</code></code> class is defined in the DevExpress.Docs.v24.1.dll assembly. Add
this assembly to your project or install the "DevExpress.Document.Processor" NuGet Package to use the <code data-control="Code" class="Code Inline"><code class=" language-cs">RichEditDocumentServerExtensions</code></code> members.
You need a license for the <a href="/products/net/office-file-api/#Pricing">DevExpress Office File API Subscription</a> or <a href="/buy">DevExpress Universal Subscription</a> to use this class in production code. </p>
</div>
<p> The following code snippet exports the first document page to an image with a specified size and JPEG format: </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">C#</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="csharp"><span class="hljs-keyword">using</span> DevExpress.XtraRichEdit;
<span class="hljs-keyword">using</span> DevExpress.XtraRichEdit.Export.Image;
<span class="hljs-keyword">using</span> DevExpress.Drawing;
<span class="hljs-keyword">using</span> (<span class="hljs-keyword">var</span> wordProcessor = <span class="hljs-keyword">new</span> RichEditDocumentServer()) {
wordProcessor.LoadDocument(<span class="hljs-string">@"C:\Documents\Alice.docx"</span>);
RichEditImageExportOptions options = <span class="hljs-keyword">new</span> RichEditImageExportOptions();
options.Format = DXImageFormat.Jpeg;
options.PageRange = <span class="hljs-string">"1"</span>;
options.LargestEdgeLength = <span class="hljs-number">1080</span>;
wordProcessor.Document.ExportToImage(<span class="hljs-string">@"C:\Documents\Image.jpeg"</span>, options);
}</code></pre>
</div>
</div> <span class="H-Separator"></span>
<h4 anchor="ofa-word-api-gutter-mirrored-margins">
<a name="ofa-word-api-gutter-mirrored-margins" class="anchor visible-anchor" href="#ofa-word-api-gutter-mirrored-margins">#</a>Gutter and Mirrored Margins
</h4>
<p> The DevExpress Word Processing Document API v24.1 allows you to specify gutter margins - extra space that ensures binding will not obscure text on printed pages. You can specify gutter position (top, left, and right) and margin size.
Use the <a href="https://docs.devexpress.com/OfficeFileAPI/DevExpress.XtraRichEdit.API.Native.Document.GutterAtTop?v=24.1" target="_blank" rel="noopener">Document.GutterAtTop</a>,
<a href="https://docs.devexpress.com/OfficeFileAPI/DevExpress.XtraRichEdit.API.Native.SectionMargins.GutterPosition?v=24.1" target="_blank" rel="noopener">SectionMargins.GutterPosition</a>, and
<a href="https://docs.devexpress.com/OfficeFileAPI/DevExpress.XtraRichEdit.API.Native.SectionMargins.Gutter?v=24.1" target="_blank" rel="noopener">SectionMargins.Gutter</a> properties to address specific usage requirements. </p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-ofa-word-api-gutter-and-mirrored-margins.png"
srcset="/subscriptions/i/24.1/24-1-ofa-word-api-gutter-and-mirrored-margins.png 1x, /subscriptions/i/24.1/24-1-ofa-word-api-gutter-and-mirrored-margins@2x.png 2x"
alt="Gutter and Mirrored Margins, DevExpress Word Processing Document API " width="1018" height="301" style="border: none" id="ctl00_ctl00_Content_Content_ctl6536"></div>
<p> The following code snippet adds a left gutter to the first document section: </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">C#</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="csharp"><span class="hljs-keyword">using</span> DevExpress.XtraRichEdit;
<span class="hljs-keyword">using</span> DevExpress.XtraRichEdit.API.Native;
<span class="hljs-keyword">using</span> DevExpress.Office.Utils;
<span class="hljs-keyword">using</span> (<span class="hljs-keyword">var</span> wordProcessor = <span class="hljs-keyword">new</span> RichEditDocumentServer()) {
wordProcessor.LoadDocument(<span class="hljs-string">@"Documents//Alice.docx"</span>);
Document document = wordProcessor.Document;
Section firstSection = wordProcessor.Document.Sections[<span class="hljs-number">0</span>];
<span class="hljs-keyword">var</span> pageMargins = firstSection.Margins;
pageMargins.GutterPosition = GutterPosition.Left;
pageMargins.Gutter = Units.InchesToDocumentsF(<span class="hljs-number">1</span>);
wordProcessor.SaveDocument(<span class="hljs-string">"Alice_formatted.docx"</span>, DocumentFormat.OpenXml);
}</code></pre>
</div>
</div>
<p> Our new <a href="https://docs.devexpress.com/OfficeFileAPI/DevExpress.XtraRichEdit.API.Native.Document.MarginType?v=24.1" target="_blank" rel="noopener">Document.MarginType</a> property allows you to define a regular or mirrored
margin type. Enable mirrored margins if you print on both sides of the paper and want to bind the printout. </p>
<p> The following code snippet enables mirrored margins and specifies an additional space value: </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">C#</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="csharp"><span class="hljs-keyword">using</span> DevExpress.XtraRichEdit;
<span class="hljs-keyword">using</span> DevExpress.XtraRichEdit.API.Native;
<span class="hljs-keyword">using</span> DevExpress.Office.Utils;
<span class="hljs-keyword">using</span> (<span class="hljs-keyword">var</span> wordProcessor = <span class="hljs-keyword">new</span> RichEditDocumentServer()) {
wordProcessor.LoadDocument(<span class="hljs-string">@"Documents//Alice.docx"</span>);
Document document = wordProcessor.Document;
<span class="hljs-comment">// Enable mirrored margins</span>
document.MarginsType = MarginsType.Mirrored;
<span class="hljs-keyword">foreach</span> (Section section <span class="hljs-keyword">in</span> wordProcessor.Document.Sections) {
<span class="hljs-keyword">var</span> pageMargins = section.Margins;
<span class="hljs-comment">// Set the value for mirrored margins</span>
pageMargins.Gutter = Units.InchesToDocumentsF(<span class="hljs-number">0.5f</span>);
}
wordProcessor.SaveDocument(<span class="hljs-string">"Alice_formatted.docx"</span>, DocumentFormat.OpenXml);
}</code></pre>
</div>
</div>
<p><a href="https://docs.devexpress.com/OfficeFileAPI/15312/word-processing-document-api/word-processing-document/sections?v=24.1#add-gutter-margins" target="_blank" rel="noopener">Documentation</a></p> <span
class="H-Separator"></span>
<h3 data-anchor="officefileapi-survey" data-toc-title="Survey - Office File API">
<a name="officefileapi-survey" class="anchor"></a>Survey - Office File API
</h3>
<h4 anchor=""> Your Feedback Matters! </h4>
<div id="ctl00_ctl00_Content_Content_SurveyContainer" data-control="survey" class="InlineSurvey">
<div data-role="SurveyContent" data-markdown="false" data-partial="false" data-multiple-results="None" data-survey-id="c8122771-0a4a-4b77-9da8-58b4ecac7064" data-auth-required="true"
data-user-data="{"IsLoggedIn":false,"IsEmployee":false,"CustomerId":null}" style="display: none;">
</div>
<div data-role="AuthRequired" style="display: block;"> Please <a href="https://www.devexpress.com/MyAccount/LogIn/?returnUrl=https%3a%2f%2fwww.devexpress.com%2fsubscriptions%2fwhats-new%2f">login</a> to complete the survey. </div>
<div data-role="Loading" style="display: none;">
<img src="../../Content/Editors/ajax-loader.gif" style="border-width:0px;">
</div>
<div data-role="Completed" style="display: none;">
<h3> Survey Completed </h3>
<p class="sys-max-width-md-80 sys-max-width-lg-60">Thank you for taking the time to complete this survey. Your responses have now been posted. If you want to follow up with additional information, feel free to send us an email at
<a href="mailto:clientservices@devexpress.com">clientservices@devexpress.com</a> anytime. </p>
</div>
<div data-role="AlreadyPassed" style="display: none;">
<h3> You've Already Completed This Survey </h3>
<p class="sys-max-width-md-80 sys-max-width-lg-60">Our records show that you have already completed this survey. If you want to follow up with additional information, send us an email at
<a href="mailto:clientservices@devexpress.com">clientservices@devexpress.com</a>.</p>
</div>
<div data-role="Expired" style="display: none;">
<h3> This survey has expired </h3>
<p>If you want to share your feedback or request new functionality, please submit a new support ticket via the <a href="https://supportcenter.devexpress.com/">DevExpress Support Center</a>. We’ll be happy to follow up.</p>
</div>
</div>
<h2 class="SectionHeader" data-anchor="maui" data-toc-title=".NET MAUI">
<a data-whatsnew-platform="maui" name="maui" class="anchor"></a>.NET MAUI Components v24.1
</h2>
<div class="WhatsNewTOC grid sys-visibility-hidden sys-visibility-hidden sys-visibility-sm-shown">
<div class="row">
<div class="col-sm-6 col-md-3 col-order-1">
<p><a href="#maui-treeview"><span>New TreeView Control</span></a></p>
<p><a href="#maui-slideview"><span>New Slide View Control</span></a></p>
<p><a href="#maui-expander"><span>New Expander Control</span></a></p>
<p><a href="#maui-scrollview"><span>New Scroll View Control</span></a></p>
<p><a href="#maui-slider"><span>New Slider Controls</span></a></p>
</div>
<div class="col-sm-6 col-md-3 col-sm-order-3 col-md-order-2">
<p><a href="#maui-scheduler"><span>Scheduler</span></a></p>
<p><a href="#maui-pdfviewer"><span>PDF Viewer</span></a></p>
<p><a href="#maui-filtering-ui"><span>Filtering UI</span></a></p>
<p><a href="#maui-collectionview"><span></span></a></p>
<p><a href="#maui-htmledit"><span>HTML Editor</span></a></p>
</div>
<div class="column-break sm">
</div>
<div class="col-sm-6 col-md-3 col-sm-order-2 col-md-order-3">
<p><a href="#maui-button"><span>Button</span></a></p>
<p><a href="#maui-orientation-settings"><span>Orientation-Based Settings</span></a></p>
<p><a href="#maui-net"><span>Target Plain .NET</span></a></p>
<p><a href="#maui-performance"><span>Optimized Memory Consumption</span></a></p>
</div>
<div class="col-sm-6 col-md-3 col-order-4">
<p><a href="#maui-build-settings"><span>Build Settings</span></a></p>
<p><a href="#maui-common-namespace"><span>Common XAML Namespace</span></a></p>
<p><a href="#maui-crm-demo"><span>DevExpress CRM Demo</span></a></p>
<p><a href="#maui-survey"><span>Survey - .NET MAUI</span></a></p>
</div>
</div>
</div>
<div class="Attention">
<p><strong>Your feedback matters.</strong><br> Please, review the description of <strong>.NET MAUI</strong>-related features below and leave your feedback at the end of the section. </p>
<p><a href="#maui-survey">Go to the survey now.</a></p>
</div>
<h3 data-anchor="maui-treeview" data-toc-title="New TreeView Control">
<a name="maui-treeview" class="anchor"></a>New TreeView Control
</h3>
<p> v24.1 includes a new .NET MAUI TreeView control. Designed to present hierarchical data, our .NET MAUI TreeView allows you to create intuitive and visually appealing user interfaces with ease. With our new .NET MAUI TreeView (<code
data-renderer="hljs" class="csharp" data-control="Code-Inline">DXTreeView</code>), you can quickly visualize files structures, organization linked relationships, hierarchical data sets, navigation menus, and more. </p>
<p></p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-maui-tree-view.png" srcset="/subscriptions/i/24.1/24-1-maui-tree-view.png 1x, /subscriptions/i/24.1/24-1-maui-tree-view@2x.png 2x" alt=".NET MAUI TreeView Control, DevExpress"
width="800" height="700" style="border: none" id="ctl00_ctl00_Content_Content_ctl6815"></div>
<p></p>
<p> Our .NET MAUI TreeView ships with the following built-in capabilities: </p>
<ul>
<li>Hierarchical and self-referential data support</li>
<li>Independent and recursive check box support</li>
<li>Filtering</li>
<li>Sorting</li>
<li>Selection</li>
<li>Swipe items</li>
<li>Item template support</li>
</ul>
<p><a href="https://docs.devexpress.com/MAUI/404896/tree-view/index?v=24.1" target="_blank" rel="noopener">Documentation</a></p> <span class="H-Separator"></span>
<h3 data-anchor="maui-slideview" data-toc-title="New Slide View Control">
<a name="maui-slideview" class="anchor"></a>New Slide View Control
</h3>
<p> v24.1 ships with a new SlideView component - designed to leverage swipe gestures (right/left or up/down) for view navigation. Our .NET MAUI SlideView component can help you create a variety of user interface solutions including
application galleries or user tutorial screens. </p> <p><span class="NativeVideo"><span><video style="width:330px;" preload="auto">
<source src="/subscriptions/i/24.1/24-1-maui-slide-view.mp4" type="video/mp4">
</video></span></span></p> <p> The DevExpress .NET MAUI SlideView includes: </p>
<ul>
<li>MVVM support (ItemsSource, ItemTemplate, ShowNext/ShowPrevious commands)</li>
<li>Item caching for improved app performance</li>
<li>Horizontal/vertical orientation</li>
<li>Looped and animated navigation</li>
</ul>
<p><a href="https://docs.devexpress.com/MAUI/404808/slide-view?v=24.1" target="_blank" rel="noopener">Documentation</a></p> <span class="H-Separator"></span>
<h3 data-anchor="maui-expander" data-toc-title="New Expander Control">
<a name="maui-expander" class="anchor"></a>New Expander Control
</h3>
<p> This release includes a .NET MAUI Expander (DXExpander) container component to help organize screen content into collapsible/expandable groups. DXExpander supports horizontal and vertical orientation and ships with fluid
collapse/expand animation effects. </p>
<p><a href="https://docs.devexpress.com/MAUI/404977/utility-controls/expander?v=24.1" target="_blank" rel="noopener">Documentation</a></p> <span class="H-Separator"></span>
<h3 data-anchor="maui-scrollview" data-toc-title="New Scroll View Control">
<a name="maui-scrollview" class="anchor"></a>New Scroll View Control
</h3>
<p> v24.1 includes a new .NET MAUI ScrollView container component designed to help you generate scroll-centric mobile interfaces. With our .NET MAUI ScrollView, users can scroll content across both vertical and horizontal directions. </p>
<p><a href="https://docs.devexpress.com/MAUI/404917/utility-controls/scroll-view?v=24.1" target="_blank" rel="noopener">Documentation</a></p> <span class="H-Separator"></span>
<h3 data-anchor="maui-slider" data-toc-title="New Slider Controls">
<a name="maui-slider" class="anchor"></a>New Slider Controls
</h3>
<p> We added two slider controls to our .NET MAUI component suite: </p>
<ul>
<li><a href="https://docs.devexpress.com/MAUI/DevExpress.Maui.Editors.DXSlider?v=24.1" target="_blank" rel="noopener">DXSlider</a> — allows users to select a numeric value.</li>
<li><a href="https://docs.devexpress.com/MAUI/DevExpress.Maui.Editors.DXRangeSlider?v=24.1" target="_blank" rel="noopener">DXRangeSlider</a> — allows users to select a range of numeric values.</li>
</ul>
<p></p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-maui-slider-control.png" srcset="/subscriptions/i/24.1/24-1-maui-slider-control.png 1x, /subscriptions/i/24.1/24-1-maui-slider-control@2x.png 2x"
alt=".NET MAUI Slider Control, DevEpress" width="578" height="760" style="border: none" id="ctl00_ctl00_Content_Content_ctl6868"></div>
<p></p>
<p>Features include:</p>
<ul>
<li>Configurable scale step</li>
<li>Minimum and maximum values</li>
<li>Customizable thumbs, tickmarks, and track</li>
<li>Thumb tooltips</li>
</ul>
<p><a href="https://docs.devexpress.com/MAUI/404789/slider-and-rangeslider/index?v=24.1" target="_blank" rel="noopener">Documentation</a></p> <span class="H-Separator"></span>
<h3 data-anchor="maui-scheduler" data-toc-title="Scheduler">
<a name="maui-scheduler" class="anchor"></a>Scheduler
</h3>
<h4 anchor="maui-scheduler-agendaview">
<a name="maui-scheduler-agendaview" class="anchor visible-anchor" href="#maui-scheduler-agendaview">#</a>Agenda View
</h4>
<p> Our new .NET MAUI AgendaView component allows you to display schedules, events, and appointments as a single day. </p>
<p></p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-maui-scheduler-agenda-view.png" srcset="/subscriptions/i/24.1/24-1-maui-scheduler-agenda-view.png 1x, /subscriptions/i/24.1/24-1-maui-scheduler-agenda-view@2x.png 2x"
alt=".NET MAUI Scheduler - Agenda View, DevExpress" width="305" height="634" style="border: none" id="ctl00_ctl00_Content_Content_ctl6887"></div>
<p></p>
<p> Features include: </p>
<ul>
<li>Ability to hide empty time slots to save screen space</li>
<li>Appointment and header appearance customization options</li>
<li>Built-in button to create a new appointment</li>
</ul>
<p><a href="https://docs.devexpress.com/MAUI/403735/scheduler-and-calendar/scheduler/views?v=24.1#agenda-view" target="_blank" rel="noopener">Documentation</a></p> <span class="H-Separator"></span>
<h3 data-anchor="maui-pdfviewer" data-toc-title="PDF Viewer">
<a name="maui-pdfviewer" class="anchor"></a>PDF Viewer
</h3>
<h4 anchor="maui-pdfviewer-doc-signatures">
<a name="maui-pdfviewer-doc-signatures" class="anchor visible-anchor" href="#maui-pdfviewer-doc-signatures">#</a>Document Signatures
</h4>
<p> With v24.1, users can sign PDF documents via our intuitive user interface (users can draw a signature at a given location or select a predefined signature). Signatures can be selected, moved and resized. Users can also specify ink
color and line width. </p>
<div class="Attention">
<p><strong>Note</strong>: To use our .NET MAUI PDF Viewer, you must purchase a separate license (the PDF Viewer is not part of the DevExpress free .NET MAUI offer). </p>
</div> <p><span class="NativeVideo"><span><video style="width:330px;" preload="auto">
<source src="/subscriptions/i/24.1/24-1-maui-pdf-signature.mp4" type="video/mp4">
</video></span></span></p> <p> To respond to user sign actions, our .NET MAUI PDF Viewer includes the following events: </p>
<ul>
<li><code data-renderer="hljs" class="csharp" data-control="Code-Inline">SignatureCreating</code> / <code data-renderer="hljs" class="csharp" data-control="Code-Inline">SignatureCreated</code></li>
<li><code data-renderer="hljs" class="csharp" data-control="Code-Inline">SignatureChanged</code></li>
<li><code data-renderer="hljs" class="csharp" data-control="Code-Inline">SignatureDeleting</code> / <code data-renderer="hljs" class="csharp" data-control="Code-Inline">SignatureDeleted</code></li>
<li><code data-renderer="hljs" class="csharp" data-control="Code-Inline">SignatureSelectionChanged</code></li>
</ul>
<p><a href="https://docs.devexpress.com/MAUI/404876/pdf-viewer/sign-document?v=24.1" target="_blank" rel="noopener">Documentation</a></p> <span class="H-Separator"></span>
<h4 anchor="maui-pdfviewer-text-selection">
<a name="maui-pdfviewer-text-selection" class="anchor visible-anchor" href="#maui-pdfviewer-text-selection">#</a>Text Selection
</h4>
<p> Users are now able to select PDF document text and highlight or copy it to the clipboard as requirements dictate. To help facilitate selection, we added a selection context menu that appears when text is selected (the menu includes
copy and highlight commands). </p>
<p> You can also interact with selected content via new API methods and events. </p>
<p><span class="FootNote"><strong>Note</strong>: To use our .NET MAUI PDF Viewer, you must purchase a separate license (the PDF Viewer is not part of the DevExpress free .NET MAUI offer). </span></p>
<p><a href="https://docs.devexpress.com/MAUI/404865/pdf-viewer/select-and-highlight?v=24.1#select-pdf-document-content" target="_blank" rel="noopener">Documentation</a></p> <span class="H-Separator"></span>
<h4 anchor="maui-pdfviewer-text-formatting-annotations">
<a name="maui-pdfviewer-text-formatting-annotations" class="anchor visible-anchor" href="#maui-pdfviewer-text-formatting-annotations">#</a>Text Formatting Annotations
</h4>
<p> v24.1 allows you to highlight selected text with different markup text annotations. The following text decorations can be added via the interface or API: </p>
<ul>
<li>Highlight</li>
<li>Underline</li>
<li>Strikethrough</li>
<li>Underline with a wavy line</li>
</ul> <p><span class="NativeVideo"><span><video style="width:330px;" preload="auto">
<source src="/subscriptions/i/24.1/24-1-maui-pdf-text-annotations.mp4" type="video/mp4">
</video></span></span></p> <p><span class="FootNote"><strong>Note</strong>: To use our .NET MAUI PDF Viewer, you must purchase a separate license (the PDF Viewer is not part of the DevExpress free .NET MAUI offer). </span></p>
<p><a href="https://docs.devexpress.com/MAUI/404865/pdf-viewer/select-and-highlight?v=24.1#highlight-the-selected-text" target="_blank" rel="noopener">Documentation</a></p> <span class="H-Separator"></span>
<h4 anchor="maui-pdfviewer-graphic-annotations">
<a name="maui-pdfviewer-graphic-annotations" class="anchor visible-anchor" href="#maui-pdfviewer-graphic-annotations">#</a>Graphic Annotations
</h4>
<p> Users can now add annotations to a PDF document, and then comment/collaborate with one another. Our .NET MAUI PDF viewer supports the following annotations: </p> <p><span class="NativeVideo"><span><video style="width:330px;"
preload="auto">
<source src="/subscriptions/i/24.1/24-1-maui-pdf-graphic-annotations.mp4" type="video/mp4">
</video></span></span></p> <ul>
<li>Sticky notes</li>
<li>Free text</li>
<li>Ellipses (Circle annotations)</li>
<li>Rectangles (Square annotations)</li>
<li>Free-hand drawing</li>
</ul>
<p><span class="FootNote"><strong>Note</strong>: To use our .NET MAUI PDF Viewer, you must purchase a separate license (the PDF Viewer is not part of the DevExpress free .NET MAUI offer). </span></p>
<p><a href="https://docs.devexpress.com/MAUI/404874/pdf-viewer/add-annotations?v=24.1" target="_blank" rel="noopener">Documentation</a></p> <span class="H-Separator"></span>
<h4 anchor="maui-pdfviewer-acro-fields">
<a name="maui-pdfviewer-acro-fields" class="anchor visible-anchor" href="#maui-pdfviewer-acro-fields">#</a>Acro Fields
</h4>
<p> AcroForms are interactive fields within a PDF document. They allow users to easily fill out forms and can help you gather data. </p>
<p> The following AcroForms are included: </p>
<ul>
<li>Text fields with following attributes supported: input character limit, read-only, multi-line, password.</li>
<li>Check boxes</li>
<li>Radio buttons</li>
<li>List boxes with single and multiple selection support</li>
<li>Combo boxes with single selection support</li>
</ul>
<p> You can also import/export AcroForm data in CSV, XML and FDF formats. </p>
<p><span class="FootNote"><strong>Note</strong>: To use our .NET MAUI PDF Viewer, you must purchase a separate license (the PDF Viewer is not part of the DevExpress free .NET MAUI offer). </span></p>
<p><a href="https://docs.devexpress.com/MAUI/404953/pdf-viewer/interactive-forms?v=24.1" target="_blank" rel="noopener">Documentation</a></p> <span class="H-Separator"></span>
<h3 data-anchor="maui-filtering-ui" data-toc-title="Filtering UI">
<a name="maui-filtering-ui" class="anchor"></a>Filtering UI
</h3>
<h4 anchor="maui-filtering-ui-predefined-filters">
<a name="maui-filtering-ui-predefined-filters" class="anchor visible-anchor" href="#maui-filtering-ui-predefined-filters">#</a>Predefined Filters
</h4>
<p> v24.1 will ship with a new PredefinedFilterCheckedChipGroupItem component. You can leverage this new UI element to add quick chip filters. Each filter chip allows you to set display text and filter criterion. Common usage scenarios
for our optimized .NET MAUI Filter UI/Filter Item include creating favorite user filters or filtering based on a predefined value range. </p>
<p></p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-maui-predefined-checked-chip-group.png"
srcset="/subscriptions/i/24.1/24-1-maui-predefined-checked-chip-group.png 1x, /subscriptions/i/24.1/24-1-maui-predefined-checked-chip-group@2x.png 2x" alt="Predefined Filters - .NET MAUI Filtering UI, DevEpress" width="330"
height="668" style="border: none" id="ctl00_ctl00_Content_Content_ctl7013"></div>
<p></p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">XAML</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="XML"><span class="hljs-tag"><<span class="hljs-name">ContentPage</span> <span class="hljs-attr">...</span>
<span class="hljs-attr">xmlns:dxe</span>=<span class="hljs-string">"clr-namespace:DevExpress.Maui.Editors;assembly=DevExpress.Maui.Editors"</span>></span>
<span class="hljs-comment"><!--...--></span>
<span class="hljs-tag"><<span class="hljs-name">dxe:PredefinedFilterCheckedChipGroupItem</span> <span class="hljs-attr">Text</span>=<span class="hljs-string">"Price"</span> <span class="hljs-attr">FieldName</span>=<span class="hljs-string">"Price"</span> <span class="hljs-attr">ShowValueCounts</span>=<span class="hljs-string">"true"</span>></span>
<span class="hljs-tag"><<span class="hljs-name">dx:PredefinedFilter</span> <span class="hljs-attr">Text</span>=<span class="hljs-string">"$0 - $500"</span> <span class="hljs-attr">FilterExpression</span>=<span class="hljs-string">"?p < 500"</span>/></span>
<span class="hljs-tag"><<span class="hljs-name">dx:PredefinedFilter</span> <span class="hljs-attr">Text</span>=<span class="hljs-string">"$500 - $2000"</span> <span class="hljs-attr">FilterExpression</span>=<span class="hljs-string">"?p >= 500 AND ?p < 2000"</span>/></span>
<span class="hljs-tag"><<span class="hljs-name">dx:PredefinedFilter</span> <span class="hljs-attr">Text</span>=<span class="hljs-string">"$2000+"</span> <span class="hljs-attr">FilterExpression</span>=<span class="hljs-string">"?p >= 2000"</span>/></span>
<span class="hljs-tag"></<span class="hljs-name">dxe:PredefinedFilterCheckedChipGroupItem</span>></span>
<span class="hljs-comment"><!--...--></span>
<span class="hljs-tag"></<span class="hljs-name">ContentPage</span>></span></code></pre>
</div>
</div>
<p><a href="https://docs.devexpress.com/MAUI/DevExpress.Maui.Editors.PredefinedFilterCheckedChipGroupItem?v=24.1" target="_blank" rel="noopener">Documentation</a></p> <span class="H-Separator"></span>
<h4 anchor="maui-collectionview-multicolumn-layout">
<a name="maui-collectionview-multicolumn-layout" class="anchor visible-anchor" href="#maui-collectionview-multicolumn-layout">#</a>Multi-Column Layout
</h4>
<p> The DevExxpress .NET MAUI CollectionView now supports multiple items within any row/column. Our multi-span layout can simplify design if/when collection view items are displayed as cards (allowing you to display more items on screen).
</p>
<p> For more information, please refer to the following API members: </p>
<ul>
<li><a href="https://docs.devexpress.com/MAUI/DevExpress.Maui.CollectionView.DXCollectionView.ItemSpanCount?v=24.1" target="_blank" rel="noopener">ItemSpanCount</a></li>
<li><a href="https://docs.devexpress.com/MAUI/DevExpress.Maui.CollectionView.DXCollectionView.ItemSpacing?v=24.1" target="_blank" rel="noopener">ItemSpacing</a></li>
<li><a href="https://docs.devexpress.com/MAUI/DevExpress.Maui.CollectionView.DXCollectionView.ItemSpanSpacing?v=24.1" target="_blank" rel="noopener">ItemSpanSpacing</a></li>
</ul>
<p></p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-maui-collection-view-multi-column-layout.png"
srcset="/subscriptions/i/24.1/24-1-maui-collection-view-multi-column-layout.png 1x, /subscriptions/i/24.1/24-1-maui-collection-view-multi-column-layout@2x.png 2x" alt="Multi-Column Layout - .NET MAUI CollectionView, DevEpress"
width="375" height="847" style="border: none" id="ctl00_ctl00_Content_Content_ctl7030"></div>
<p></p> <span class="H-Separator"></span>
<h4 anchor="maui-collectionview-ripple-effect">
<a name="maui-collectionview-ripple-effect" class="anchor visible-anchor" href="#maui-collectionview-ripple-effect">#</a>Ripple Effect
</h4>
<p> Our .NET MAUI CollectionView now supports ripple effects for tapped items. Ripple animations can help you create more intuitive user experiences. To activate ripple effects, enable the
<a href="https://docs.devexpress.com/MAUI/DevExpress.Maui.CollectionView.DXCollectionView.UseRippleEffect?v=24.1" target="_blank" rel="noopener">UseRippleEffect</a> property. </p>
<p></p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-maui-collection-view-ripple-effect-hd.gif" alt="Ripple Effect - .NET MAUI CollectionView, DevEpress" width="295" height="91" style="border: none"
id="ctl00_ctl00_Content_Content_ctl7043"></div>
<p></p> <span class="H-Separator"></span>
<h4 anchor="maui-collectionview-item-group-separators">
<a name="maui-collectionview-item-group-separators" class="anchor visible-anchor" href="#maui-collectionview-item-group-separators">#</a>Item and Group Separators
</h4>
<p> Separators are common elements and are used in most collections. With our most recent update, you no longer need to add a separator to your item template. This enhancement simplifies XAML code and template arrangement logic. The
following APIs will help you add separators to our .NET MAUI CollectionView: </p>
<ul>
<li><a href="https://docs.devexpress.com/MAUI/DevExpress.Maui.CollectionView.DXCollectionView.GroupItemSeparatorColor?v=24.1" target="_blank" rel="noopener">GroupItemSeparatorColor</a></li>
<li><a href="https://docs.devexpress.com/MAUI/DevExpress.Maui.CollectionView.DXCollectionView.GroupItemSeparatorCapMargin?v=24.1" target="_blank" rel="noopener">GroupItemSeparatorCapMargin</a></li>
<li><a href="https://docs.devexpress.com/MAUI/DevExpress.Maui.CollectionView.DXCollectionView.GroupItemSeparatorThickness?v=24.1" target="_blank" rel="noopener">GroupItemSeparatorThickness</a></li>
<li><a href="https://docs.devexpress.com/MAUI/DevExpress.Maui.CollectionView.DXCollectionView.ItemSeparatorColor?v=24.1" target="_blank" rel="noopener">ItemSeparatorColor</a></li>
<li><a href="https://docs.devexpress.com/MAUI/DevExpress.Maui.CollectionView.DXCollectionView.ItemSeparatorThickness?v=24.1" target="_blank" rel="noopener">ItemSeparatorThickness</a></li>
<li><a href="https://docs.devexpress.com/MAUI/DevExpress.Maui.CollectionView.DXCollectionView.ItemSeparatorCapMargin?v=24.1" target="_blank" rel="noopener">ItemSeparatorCapMargin</a></li>
<li><a href="https://docs.devexpress.com/MAUI/DevExpress.Maui.CollectionView.DXCollectionView.ItemSeparatorShowBeforeGroup?v=24.1" target="_blank" rel="noopener">ItemSeparatorShowBeforeGroup</a></li>
</ul> <span class="H-Separator"></span>
<h3 data-anchor="maui-htmledit" data-toc-title="HTML Editor">
<a name="maui-htmledit" class="anchor"></a>HTML Editor
</h3>
<h4 anchor="maui-htmleditor-tables">
<a name="maui-htmleditor-tables" class="anchor visible-anchor" href="#maui-htmleditor-tables">#</a>Tables
</h4>
<p> Users can now add and edit tables within our .NET MAUI HTML Editor. Like other DevExpress .NET MAUI controls, user interface elements are designed to maximize ease-of-use on mobile devices/form factors. </p>
<p><a href="https://docs.devexpress.com/MAUI/404638/html-edit/modify-html-markup?v=24.1#insert-and-remove-tables" target="_blank" rel="noopener">Documentation</a></p>
<p></p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-maui-htmledit-tables.png" srcset="/subscriptions/i/24.1/24-1-maui-htmledit-tables.png 1x, /subscriptions/i/24.1/24-1-maui-htmledit-tables@2x.png 2x"
alt="Tables - .NET MAUI HTML Editor, DevEpress" width="495" height="425" style="border: none" id="ctl00_ctl00_Content_Content_ctl7068"></div>
<p></p> <span class="H-Separator"></span>
<h3 data-anchor="maui-button" data-toc-title="Button">
<a name="maui-button" class="anchor"></a>Button
</h3>
<h4 anchor="maui-button-ripple-effect">
<a name="maui-button-ripple-effect" class="anchor visible-anchor" href="#maui-button-ripple-effect">#</a>Ripple Effect
</h4>
<p> We added ripple effect support to our .NET MAUI Button component. Use the <a href="https://docs.devexpress.com/MAUI/DevExpress.Maui.Core.DXButtonBase.UseRippleEffect?v=24.1" target="_blank" rel="noopener">UseRippleEffect</a> property
to activate ripple animations for individual buttons. </p> <p><img src="/subscriptions/i/24.1/24-1-maui-button-ripple-effect.gif"
srcset="/subscriptions/i/24.1/24-1-maui-button-ripple-effect.gif 1x, /subscriptions/i/24.1/24-1-maui-button-ripple-effect@2x.gif 2x" alt="Ripple Effect - .NET MAUI Button, DevEpress" width="194" height="54" style="border: none"
id="ctl00_ctl00_Content_Content_ctl7085"></p> <span class="H-Separator"></span>
<h3 data-anchor="maui-orientation-settings" data-toc-title="Orientation-Based Settings">
<a name="maui-orientation-settings" class="anchor"></a>Orientation-Based Settings
</h3>
<p> With our new <a href="https://docs.devexpress.com/MAUI/DevExpress.Maui.Core.OnOrientationExtension?v=24.1" target="_blank" rel="noopener">OnOrientation</a> markup extension, it's much easier to implement a responsive UI based on
device orientation. There is no need to write C# code and handle orientation changes: you can specify orientation-based settings in XAML. </p>
<p><a href="https://docs.devexpress.com/MAUI/404287/common-concepts/specify-device-specific-settings?v=24.1#xaml-use-the-onorientation-extension" target="_blank" rel="noopener">Documentation</a></p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">XAML</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="XML"><span class="hljs-tag"><<span class="hljs-name">ContentPage</span> <span class="hljs-attr">...</span> <span class="hljs-attr">xmlns:dx</span>=<span class="hljs-string">"clr-namespace:DevExpress.Maui.Core;assembly=DevExpress.Maui.Core"</span>></span>
<span class="hljs-comment"><!--...--></span>
<span class="hljs-tag"><<span class="hljs-name">dx:DXButton</span> <span class="hljs-attr">Content</span>=<span class="hljs-string">"Click"</span> <span class="hljs-attr">Padding</span>=<span class="hljs-string">"{dx:OnOrientation Portrait='10,6', Landscape='12,8'}"</span>/></span>
<span class="hljs-comment"><!--...--></span>
<span class="hljs-tag"></<span class="hljs-name">ContentPage</span>></span></code></pre>
</div>
</div> <span class="H-Separator"></span>
<h3 data-anchor="maui-net" data-toc-title="Target Plain .NET">
<a name="maui-net" class="anchor"></a>Target Plain .NET
</h3>
<p> As you may know, the XUnit testing library requires standard .NET 8 (not .NET 8.0 Android/iOS) to be referenced as a target framework within project settings. In previous versions, you could not use our controls in a standard .NET 8
project and therefore you could not use XUnit. With v23.2.5, you can target standard .NET 8 in projects when using DevExpress .NET MAUI component libraries. </p>
<p><a href="https://docs.devexpress.com/MAUI/404781/unit-testing" target="_blank" rel="noopener">Documentation</a></p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">XAML</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="XML"><span class="hljs-tag"><<span class="hljs-name">Project</span> <span class="hljs-attr">Sdk</span>=<span class="hljs-string">"Microsoft.NET.Sdk"</span>></span>
<span class="hljs-tag"><<span class="hljs-name">PropertyGroup</span>></span>
<span class="hljs-tag"><<span class="hljs-name">TargetFrameworks</span>></span>
net8.0;net8.0-android;net8.0-ios
<span class="hljs-tag"></<span class="hljs-name">TargetFrameworks</span>></span>
<span class="hljs-tag"><<span class="hljs-name">OutputType</span> <span class="hljs-attr">Condition</span>=<span class="hljs-string">"'$(TargetFramework)' != 'net8.0'"</span>></span>
Exe
<span class="hljs-tag"></<span class="hljs-name">OutputType</span>></span>
<span class="hljs-comment"><!-- ... --></span>
<span class="hljs-tag"></<span class="hljs-name">PropertyGroup</span>></span>
<span class="hljs-comment"><!-- ... --></span>
<span class="hljs-tag"></<span class="hljs-name">Project</span>></span></code></pre>
</div>
</div> <span class="H-Separator"></span>
<h3 data-anchor="maui-performance" data-toc-title="Optimized Memory Consumption">
<a name="maui-performance" class="anchor"></a>Optimized Memory Consumption
</h3>
<p> With this update, DevExpress .NET MAUI components allow you to ship mobile apps with a significantly lower memory footprint (prevents memory-related issues and improves overall performance). </p> <span class="H-Separator"></span>
<h3 data-anchor="maui-build-settings" data-toc-title="Build Settings">
<a name="maui-build-settings" class="anchor"></a>Build Settings
</h3>
<p> The DevExpress.Maui.Core NuGet package now includes ".props" and ".targets" files for default build settings. These settings allow you to maximize performance and minimize application size across a variety of usage scenarios.
Additionally, they allow you to use Emit as needed (to generate Entity Framework Core classes dynamically). </p>
<p><a href="https://docs.devexpress.com/MAUI/404979/common-concepts/build-configuration?v=24.1" target="_blank" rel="noopener">Documentation</a></p> <span class="H-Separator"></span>
<h3 data-anchor="maui-common-namespace" data-toc-title="Common XAML Namespace">
<a name="maui-common-namespace" class="anchor"></a>Common XAML Namespace
</h3>
<p> You can now reference all DevExpress .NET MAUI Controls with a single "xmlns:dx="http://schemas.devexpress.com/maui" XAML namespace. To update app XAML, simply use our
<a href="https://www.nuget.org/packages/DevExpress.Maui.XamlTools" target="_blank" rel="noopener">XamlTool</a>. </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">v24.1</li>
<li>Previous Versions</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="XML"><span class="hljs-tag"><<span class="hljs-name">ContentPage</span> <span class="hljs-attr">...</span>
<span class="hljs-attr">xmlns:dx</span>=<span class="hljs-string">"http://schemas.devexpress.com/maui"</span></span></code></pre>
</div>
<div class="CodeContainer">
<pre><code data-renderer="hljs" class="XML"><span class="hljs-tag"><<span class="hljs-name">ContentPage</span> <span class="hljs-attr">...</span>
<span class="hljs-attr">xmlns:dx</span>=<span class="hljs-string">"clr-namespace:DevExpress.Maui.Core;assembly=DevExpress.Maui.Core"</span>
<span class="hljs-attr">xmlns:dxcv</span>=<span class="hljs-string">"clr-namespace:DevExpress.Maui.CollectionView;assembly=DevExpress.Maui.CollectionView"</span>
<span class="hljs-attr">xmlns:dxg</span>=<span class="hljs-string">"clr-namespace:DevExpress.Maui.DataGrid;assembly=DevExpress.Maui.DataGrid"</span>
<span class="hljs-attr">xmlns:dxco</span>=<span class="hljs-string">"clr-namespace:DevExpress.Maui.Controls;assembly=DevExpress.Maui.Controls"</span></span></code></pre>
</div>
</div> <span class="H-Separator"></span>
<h3 data-anchor="maui-crm-demo" data-toc-title="DevExpress CRM Demo">
<a name="maui-crm-demo" class="anchor"></a>DevExpress CRM Demo
</h3>
<p> Our new real-life application demonstrates the following features/capabilities: </p>
<ul>
<li>Mobile-friendly CRUD flow (using an SQLite database).</li>
<li>Basic and advanced .NET MAUI filtering UI elements.</li>
<li>Master-detail view that leverages the DevExpress .NET MAUI BottomSheet control to display selected item info.</li>
<li>Export .NET MAUI DataGrid data to Excel and PDF.</li>
<li>Import Excel file data and display it within the DevExpress .NET MAUI DataGrid.</li>
<li>Document processing using the DevExpress Office File API library.</li>
<li>Report generation powered by DevExpress Reports.</li>
<li>Material Design 3 theme support.</li>
<li>Data visualization using charts and circular gauge.</li>
</ul> <p><img src="/subscriptions/i/24.1/24-1-maui-crm-demo.png" alt="" width="1150" height="776" style="border: none" id="ctl00_ctl00_Content_Content_ctl7150"></p> <p> Download our free demo app from the Google Play Store,
TestFlight, or GitHub, and see DevExpress MAUI UI controls in action. </p> <p>
<a href="https://play.google.com/store/apps/details?id=com.devexpress.CrmDemo&pcampaignid=web_share" target="_blank" rel="noopener"><img src="/products/i/google-play-hd.png" alt="Download Demos via Google Play" width="169" height="50" style="border: none" id="ctl00_ctl00_Content_Content_ctl7157"></a>
<a href="https://testflight.apple.com/join/R4YeuQ49" target="_blank" rel="noopener"><img src="/products/i/ios-testflight.png" srcset="/products/i/ios-testflight.png 1x, /products/i/ios-testflight@2x.png 2x" alt="Download Demos for iOS via TestFlight" width="166" height="50" style="border: none" id="ctl00_ctl00_Content_Content_ctl7160"></a>
</p> <p><a href="https://github.com/DevExpress-Examples/maui-crm-demo" target="_blank" rel="noopener">Source Code for Demo App (iOS and Android)</a></p> <span class="H-Separator"></span>
<h3 data-anchor="maui-survey" data-toc-title="Survey - .NET MAUI">
<a name="maui-survey" class="anchor"></a>Survey - .NET MAUI
</h3>
<h4 anchor=""> Your Feedback Matters! </h4>
<div id="ctl00_ctl00_Content_Content_SurveyContainer" data-control="survey" class="InlineSurvey">
<div data-role="SurveyContent" data-markdown="false" data-partial="false" data-multiple-results="None" data-survey-id="d3b68c49-34b6-4c56-87f1-cad87b0c113c" data-auth-required="true"
data-user-data="{"IsLoggedIn":false,"IsEmployee":false,"CustomerId":null}" style="display: none;">
</div>
<div data-role="AuthRequired" style="display: block;"> Please <a href="https://www.devexpress.com/MyAccount/LogIn/?returnUrl=https%3a%2f%2fwww.devexpress.com%2fsubscriptions%2fwhats-new%2f">login</a> to complete the survey. </div>
<div data-role="Loading" style="display: none;">
<img src="../../Content/Editors/ajax-loader.gif" style="border-width:0px;">
</div>
<div data-role="Completed" style="display: none;">
<h3> Survey Completed </h3>
<p class="sys-max-width-md-80 sys-max-width-lg-60"> Thank you for taking the time to complete this survey. Your responses have now been posted. If you want to follow up with additional information, feel free to send us an email at
<a href="mailto:clientservices@devexpress.com">clientservices@devexpress.com</a> anytime. </p>
</div>
<div data-role="AlreadyPassed" style="display: none;">
<h3> You've Already Completed This Survey </h3>
<p class="sys-max-width-md-80 sys-max-width-lg-60"> Our records show that you have already completed this survey. If you want to follow up with additional information, send us an email at
<a href="mailto:clientservices@devexpress.com">clientservices@devexpress.com</a>. </p>
</div>
<div data-role="Expired" style="display: none;">
<h3> This survey has expired </h3>
<p>If you want to share your feedback or request new functionality, please submit a new support ticket via the <a href="https://supportcenter.devexpress.com/">DevExpress Support Center</a>. We’ll be happy to follow up.</p>
</div>
</div>
<h2 class="SectionHeader" data-anchor="xaf" data-toc-title="XAF - App Framework">
<a data-whatsnew-platform="xaf" name="xaf" class="anchor"></a>XAF: Cross-Platform .NET App UI & Web API v24.1
</h2>
<div class="WhatsNewTOC grid sys-visibility-hidden sys-visibility-hidden sys-visibility-sm-shown">
<div class="row">
<div class="col-sm-6 col-md-3 col-order-1">
<p><a href="#xaf-blazor-crud"><span>Blazor – CRUD</span></a></p>
<p><a href="#xaf-blazor-usability"><span>Blazor – Usability</span></a></p>
</div>
<div class="col-sm-6 col-md-3 col-sm-order-3 col-md-order-2">
<p><a href="#xaf-blazor-extra-modules"><span>Blazor – Extra Modules</span></a></p>
<p><a href="#xaf-entity-framework"><span>Entity Framework</span></a></p>
</div>
<div class="column-break sm">
</div>
<div class="col-sm-6 col-md-3 col-sm-order-2 col-md-order-3">
<p><a href="#xaf-security"><span>Security System</span></a></p>
<p><a href="#xaf-multi-tenancy"><span>Multi-Tenancy</span></a></p>
</div>
<div class="col-sm-6 col-md-3 col-order-4">
<p><a href="#xaf-cross-platform"><span>Cross-Platform Enhancements</span></a></p>
<p><a href="#xaf-survey"><span>Survey - XAF & Web API Service</span></a></p>
</div>
</div>
</div>
<div class="Attention">
<p><strong>Your feedback matters.</strong><br> Please, review the description of <strong>Cross-Platform .NET App UI (XAF)</strong> and <strong>Web API Service</strong> related features below and leave your feedback at the end of the
section. </p>
<p><a href="#xaf-survey">Go to the survey now.</a></p>
</div>
<h3 data-anchor="xaf-blazor-crud" data-toc-title="Blazor – CRUD">
<a name="xaf-blazor-crud" class="anchor"></a>Blazor – CRUD
</h3>
<h4 anchor="xaf-blazor-batch-edit-in-grid-list-editor">
<a name="xaf-blazor-batch-edit-in-grid-list-editor" class="anchor visible-anchor" href="#xaf-blazor-batch-edit-in-grid-list-editor">#</a>Batch / Cell Edit in Grid List Editor
</h4>
<p> Batch Edit support officially ships in XAF Blazor v24.1 via a single option
(<a href="https://docs.devexpress.com/eXpressAppFramework/113249/ui-construction/views/list-view-edit-modes?v=24.1#in-place-editing-customization-the-inlineeditmode-property-1" target="_blank" rel="noopener">InlineEditMode = Batch</a>)
- much like its XAF WebForms counterpart. </p> <p><span class="NativeVideo"><span><video style="width:1000px;" preload="auto">
<source src="/subscriptions/i/24.1/24-1-xaf-blazor-crud-batch-edit.mp4" type="video/mp4">
</video></span></span></p>
<h4 anchor="">
</h4>
<div class="Attention">
<p class="sys-h-align-left"><strong>Roman Shelomanov</strong><br> We have been testing this since 24.1 EAP and now in 24.1.2 Beta and it works fantastic. Thank you so much for getting it done, it's one extra step to get Blazor to
feature parity with WinForms that lots of us have used and loved over the years. </p>
</div>
<h4 anchor="xaf-blazor-export-to-excel">
<a name="xaf-blazor-export-to-excel" class="anchor visible-anchor" href="#xaf-blazor-export-to-excel">#</a>Export Data from Grid List Editor to Excel when DataAccessMode = Server
</h4>
<p> Our Blazor Components and XAF v24.1 support <a href="https://docs.devexpress.com/eXpressAppFramework/113362/shape-export-print-data/printing-exporting-in-listview/exporting?v=24.1" target="_blank" rel="noopener">Excel export</a>
functionality for grids bound to server-side data (for both EF Core and XPO ORM). To export data to Excel, the DevExpress Blazor Grid will display a loading indicator and download all records from a data source. </p> <p></p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-xaf-blazor-export-to-excel.png" srcset="/subscriptions/i/24.1/24-1-xaf-blazor-export-to-excel.png 1x, /subscriptions/i/24.1/24-1-xaf-blazor-export-to-excel@2x.png 2x"
alt="Export Data from Grid List Editor to Excel - XAF for Blazor, DevExpress" width="882" height="442" style="border: none" id="ctl00_ctl00_Content_Content_ctl7501"></div>
<p></p> <span class="H-Separator"></span>
<h4 anchor="xaf-blazor-grid-add-fields-to-customization-form">
<a name="xaf-blazor-grid-add-fields-to-customization-form" class="anchor visible-anchor" href="#xaf-blazor-grid-add-fields-to-customization-form">#</a>Add New Fields into the Customization Form of the Grid and Layout Controls at Runtime
</h4>
<p> XAF WinForms apps include an Object Model dialog. With it, end-users can search, tick or untick data model fields (including sub-fields and collections), which are not yet displayed in the grid or layout control (as part of the Column
Chooser or Customization Form). </p>
<p> Much like Microsoft Office apps, this capability allows users to fully customize list and detail forms (based on the structure of a data model). Again, this is helpful when developers need to address changes to business requirements
without redeployment. For more information, refer to
<a href="https://docs.devexpress.com/eXpressAppFramework/404353/ui-construction/views/layout/view-items-layout-customization-blazor?v=24.1" target="_blank" rel="noopener">Runtime Layout Customization in ASP.NET Core Blazor Applications</a>.
</p>
<p> XAF Blazor v24.1 provides a similar experience for both ListView
(<a href="https://docs.devexpress.com/eXpressAppFramework/113679/ui-construction/views/layout/list-view-columns-customization?v=24.1#column-chooser" target="_blank" rel="noopener">Column Chooser</a>) and DetailView
(<a href="https://docs.devexpress.com/eXpressAppFramework/404353/ui-construction/views/layout/view-items-layout-customization-blazor?v=24.1#add-reference-properties-to-a-detail-view" target="_blank" rel="noopener">Customization Form</a>).
This feature removes the need for many UI customizations in the design-time Model Editor (inside Visual Studio) - something many of you love in XAF WinForms UI. Of course, you can also disable these runtime capabilities for end-users.
</p>
<p></p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-xaf-blazor-customization-form-1.png"
srcset="/subscriptions/i/24.1/24-1-xaf-blazor-customization-form-1.png 1x, /subscriptions/i/24.1/24-1-xaf-blazor-customization-form-1@2x.png 2x" alt="Add New Fields into the Customization Form of the Grid - XAF for Blazor, DevExpress"
width="1003" height="574" style="border: none" id="ctl00_ctl00_Content_Content_ctl7524"></div>
<p></p>
<p></p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-xaf-blazor-customization-form-2.png"
srcset="/subscriptions/i/24.1/24-1-xaf-blazor-customization-form-2.png 1x, /subscriptions/i/24.1/24-1-xaf-blazor-customization-form-2@2x.png 2x"
alt="Add New Fields into the Customization Form of the Layout Controls - XAF for Blazor, DevExpress" width="1003" height="574" style="border: none" id="ctl00_ctl00_Content_Content_ctl7526"></div>
<p></p> <span class="H-Separator"></span>
<h3 data-anchor="xaf-blazor-usability" data-toc-title="Blazor – Usability">
<a name="xaf-blazor-usability" class="anchor"></a>Blazor – Usability
</h3>
<h4 anchor="">
</h4>
<div class="Attention">
<p class="sys-h-align-left"><strong>Philippe Petrussa</strong><br> As mentioned in one of your posts, DevExpress has strongly reduced the boilerplate code to integrate Blazor editors in XAF Blazor. Great Job! </p>
</div>
<h4 anchor="xaf-blazor-tabbed-mdi">
<a name="xaf-blazor-tabbed-mdi" class="anchor visible-anchor" href="#xaf-blazor-tabbed-mdi">#</a>Tabbed MDI Support
</h4>
<p> Tabbed MDI is a multiple document interface (MDI) UI metaphor found in many modern applications (including your favorite Web browser or Microsoft Outlook Web). It is a robust interface that maximizes document screen real estate,
especially when working with multiple documents, email messages, etc. </p>
<p><a href="https://docs.devexpress.com/eXpressAppFramework/DevExpress.ExpressApp.UIType?v=24.1" target="_blank" rel="noopener">Tabbed MDI</a> is enabled in XAF WinForms apps by default, and XAF Blazor provides a similar user experience
in v24.1. You can also customize Tabbed MDI in the Model Editor as follows: </p>
<ul>
<li> Restore previously opened tabs between application runs (<code data-renderer="hljs" class="csharp" data-control="Code-Inline">RestoreTabbedMdiLayout</code> = True by default). </li>
<li> Refresh View data source on tab focus (<code data-renderer="hljs" class="csharp" data-control="Code-Inline">RefreshViewOnTabFocus</code> = False by default) </li>
<li> Display or hide tab images (<code data-renderer="hljs" class="csharp" data-control="Code-Inline">ShowTabImage</code> = True by default) </li>
</ul>
<p> In addition, you can access the underlying tab control in code and configure it as needed using a Controller (in the "SolutionName.Blazor" project). For instance, you can load tabs on demand or simultaneously: </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">C#</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="csharp"><span class="hljs-function"><span class="hljs-keyword">protected</span> <span class="hljs-keyword">override</span> <span class="hljs-keyword">void</span> <span class="hljs-title">OnFrameAssigned</span>()</span> {
<span class="hljs-keyword">base</span>.OnFrameAssigned();
Frame.TemplateChanged += Frame_TemplateChanged;
}
<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">Frame_TemplateChanged</span>(<span class="hljs-params"><span class="hljs-built_in">object</span> sender, EventArgs e</span>)</span> {
<span class="hljs-keyword">if</span>(Frame.Template <span class="hljs-keyword">is</span> ITabbedMdiMainFormTemplate template) {
template.TabsModel.RenderMode = DevExpress.Blazor.TabsRenderMode.AllTabs;
}
}</code></pre>
</div>
</div>
<p></p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-xaf-blazor-tabbed-mdi.png" srcset="/subscriptions/i/24.1/24-1-xaf-blazor-tabbed-mdi.png 1x, /subscriptions/i/24.1/24-1-xaf-blazor-tabbed-mdi@2x.png 2x"
alt="Tabbed MDI Support - XAF for Blazor, DevExpress" width="1003" height="451" style="border: none" id="ctl00_ctl00_Content_Content_ctl7554"></div>
<p></p> <span class="H-Separator"></span>
<h4 anchor="xaf-blazor-create-custom-properties">
<a name="xaf-blazor-create-custom-properties" class="anchor visible-anchor" href="#xaf-blazor-create-custom-properties">#</a>Simplified Creation of Custom Blazor Property and List Editors
</h4>
<p> In v24.1, we reduced boilerplate code for many popular UI customization scenarios: </p>
<ul>
<li>Create custom Property and List Editors.</li>
<li>List/Property Editors access control options in code without adapters.</li>
</ul>
<p> Previously, XAF Blazor developers had to create intermediate
<a href="https://docs.devexpress.com/eXpressAppFramework/402189/ui-construction/view-items-and-property-editors/property-editors/implement-a-property-editor-based-on-custom-components-blazor#component-adapter" target="_blank" rel="noopener">Component Adapter, Renderer and other boilerplate classes</a>,
which were cumbersome or noisy. </p>
<p> With this release, the amount of required code is much less (like its XAF WinForms counterpart). Our built-in <code data-renderer="hljs" class="csharp" data-control="Code-Inline">ComponentModel</code> classes now handle component
<code data-renderer="hljs" class="csharp" data-control="Code-Inline">ValueChanged</code> events (TextChanged, DateChanged, TimeChanged, etc.) and automatically read and write component values (text, date, time, etc.). The minimal
implementation of a
<a href="https://docs.devexpress.com/eXpressAppFramework/402189/ui-construction/view-items-and-property-editors/property-editors/implement-a-property-editor-based-on-custom-components-blazor?v=24.1" target="_blank" rel="noopener">Blazor property editor</a>
based on <code data-renderer="hljs" class="csharp" data-control="Code-Inline">DxTextBoxModel</code> component model is as follows in v24.1: </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">C#</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="csharp">[<span class="hljs-meta">PropertyEditor(typeof(string), false)</span>]
<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">CustomStringPropertyEditor</span> : <span class="hljs-title">BlazorPropertyEditorBase</span> {
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">CustomStringPropertyEditor</span>(<span class="hljs-params">Type objectType, IModelMemberViewItem model</span>) : <span class="hljs-title">base</span>(<span class="hljs-params">objectType, model</span>)</span> { }
<span class="hljs-keyword">public</span> <span class="hljs-keyword">override</span> DxTextBoxModel ComponentModel => (DxTextBoxModel)<span class="hljs-keyword">base</span>.ComponentModel;
<span class="hljs-function"><span class="hljs-keyword">protected</span> <span class="hljs-keyword">override</span> IComponentModel <span class="hljs-title">CreateComponentModel</span>()</span> => <span class="hljs-keyword">new</span> DxTextBoxModel();
}</code></pre>
</div>
</div>
<p> Controller code used to customize a List View or DetailView Property Editor control is also simpler in v24.1 (since no adapter is required): </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">C#</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="csharp"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">CustomizeDateEditorController</span> : <span class="hljs-title">ViewController</span><<span class="hljs-title">DetailView</span>> {
<span class="hljs-function"><span class="hljs-keyword">protected</span> <span class="hljs-keyword">override</span> <span class="hljs-keyword">void</span> <span class="hljs-title">OnActivated</span>()</span> {
<span class="hljs-keyword">base</span>.OnActivated();
View.CustomizeViewItemControl<DateTimePropertyEditor>(<span class="hljs-keyword">this</span>, CustomizeDateTimeEditor);
}
<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">CustomizeDateTimeEditor</span>(<span class="hljs-params">DateTimePropertyEditor propertyEditor</span>)</span> {
<span class="hljs-comment">// v23.2</span>
<span class="hljs-comment">//if(propertyEditor.Control is DxDateEditAdapter adapter) {</span>
<span class="hljs-comment">// adapter.ComponentModel.TimeSectionVisible = true;</span>
<span class="hljs-comment">//}</span>
<span class="hljs-comment">// v24.1+</span>
propertyEditor.ComponentModel.TimeSectionVisible = <span class="hljs-literal">true</span>;
}
}</code></pre>
</div>
</div>
<p> Our newest <a href="https://github.com/DevExpress-Examples/xaf-create-multitenant-application/tree/24.1.2%2B" target="_blank" rel="noopener">Outlook Inspired Demo app</a> contains many custom Property and List Editors. It’s a great
source for UX validation/comparison between v23.2 and v24.1. </p>
<p><a href="https://supportcenter.devexpress.com/ticket/details/t1230710/blazor-the-listeditor-control-propertyeditor-control-and-viewitem-control-properties" target="_blank" rel="noopener">Breaking Change</a></p>
<h4 anchor="">
</h4>
<div class="Attention">
<p class="sys-h-align-left"><strong>Martin Praxmarer</strong><br> I really love it – I have integrated the new Blazor Progress Bar in nearly 5 minutes – without creating an adapter – nor an razor component! Thank you Guys – simply
wonderful! </p>
</div>
<h4 anchor="xaf-blazor-accessibility">
<a name="xaf-blazor-accessibility" class="anchor visible-anchor" href="#xaf-blazor-accessibility">#</a>Accessibility Enhancements and Keyboard Support
</h4>
<p> Currently, XAF (UI for ASP.NET Core Blazor, WinForms, and ASP.NET WebForms) ships with partial accessibility support mirroring those found in corresponding DevExpress UI controls across respective UI platforms: </p>
<ul>
<li><a href="https://docs.devexpress.com/Blazor/404749/common-concepts/accessibility" target="_blank" rel="noopener">DevExpress ASP.NET Core Blazor</a></li>
<li><a href="https://docs.devexpress.com/WindowsForms/404293/build-an-application/accessibility" target="_blank" rel="noopener">DevExpress WinForms</a></li>
<li><a href="https://docs.devexpress.com/AspNet/5294/common-concepts/accessibility-support" target="_blank" rel="noopener">DevExpress ASP.NET Web Forms</a></li>
<li><a href="https://js.devexpress.com/DevExtreme/23_2/Guide/Common/Accessibility/" target="_blank" rel="noopener">DevExpress DevExtreme</a> (DevExtreme UI controls are used in XAF ASP.NET Core Blazor and ASP.NET Web Forms UI.)</li>
</ul>
<p> XAF Blazor also ships with its own set of UI components/elements (like property editors and action containers). In v24.1, we extended accessibility support and improved keyboard support for all XAF Blazor UI elements (~20% of
scenarios). XAF accessibility support will also level up automatically as soon as we enhance accessibility in DevExpress Blazor UI components throughout 2024. </p>
<p> Our Blazor Grid's keyboard navigation option also officially ships and is enabled by default in XAF Blazor. </p>
<p><a href="https://docs.devexpress.com/eXpressAppFramework/404762/accessibility?v=24.1" target="_blank" rel="noopener">Documentation</a></p> <span class="H-Separator"></span>
<h3 data-anchor="xaf-blazor-extra-modules" data-toc-title="Blazor – Extra Modules">
<a name="xaf-blazor-extra-modules" class="anchor"></a>Blazor – Extra Modules
</h3>
<h4 anchor="xaf-blazor-scheduler">
<a name="xaf-blazor-scheduler" class="anchor visible-anchor" href="#xaf-blazor-scheduler">#</a>Scheduler Module - Shared/Multiple Resources
</h4>
<p> The underlying Blazor scheduler component (<a href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxScheduler" target="_blank" rel="noopener">DxScheduler</a>) supports multiple resources for a scheduler appointment/event in
v24.1. XAF Blazor Scheduler module now allows you to use shared resources as well. Previously, only a single resource was allowed in DxScheduler, and XAF displayed a validation error message when you attempted to link multiple resources
to an appointment. </p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-xaf-blazor-scheduler.png" srcset="/subscriptions/i/24.1/24-1-xaf-blazor-scheduler.png 1x, /subscriptions/i/24.1/24-1-xaf-blazor-scheduler@2x.png 2x"
alt="Scheduler Module - XAF for Blazor, DevExpress" width="1003" height="664" style="border: none" id="ctl00_ctl00_Content_Content_ctl7627"></div>
<p><a href="https://docs.devexpress.com/eXpressAppFramework/112811/event-planning-and-notifications/scheduler-module?v=24.1" target="_blank" rel="noopener">Documentation</a></p> <span class="H-Separator"></span>
<h4 anchor="xaf-blazor-notifications">
<a name="xaf-blazor-notifications" class="anchor visible-anchor" href="#xaf-blazor-notifications">#</a>Notifications Module Support
</h4>
<p> XAF Blazor v24.1 supports our <a href="https://docs.devexpress.com/eXpressAppFramework/113690/event-planning-and-notifications/notifications/notifications-module-overview" target="_blank" rel="noopener">Notifications Module</a>. The
module allows you to display reminders for scheduler appointments or any custom objects (such as tasks). The detail form for a scheduler appointment/event also allows you to configure reminders like those available in Microsoft Outlook.
</p>
<p> With the help of the Notifications Module, your app can display a popup window before appointment/event start times. </p>
<div class="Attention">
<p class="sys-h-align-left"><strong>Note</strong>: our Notifications module does not have to be bound to the Scheduler module: it can display notifications that originate from anywhere. In the latter instance, your goal as a developer
is to provide the notifications service with notification items and the service will process them as required. </p>
</div>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-xaf-blazor-notification-module-1.png"
srcset="/subscriptions/i/24.1/24-1-xaf-blazor-notification-module-1.png 1x, /subscriptions/i/24.1/24-1-xaf-blazor-notification-module-1@2x.png 2x" alt="Notifications Module - XAF for Blazor, DevExpress" width="1003" height="574"
style="border: none" id="ctl00_ctl00_Content_Content_ctl7649"></div>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-xaf-blazor-notification-module-2.png"
srcset="/subscriptions/i/24.1/24-1-xaf-blazor-notification-module-2.png 1x, /subscriptions/i/24.1/24-1-xaf-blazor-notification-module-2@2x.png 2x" alt="Notifications Module - XAF for Blazor, DevExpress" width="1048" height="764"
style="border: none" id="ctl00_ctl00_Content_Content_ctl7650"></div> <span class="H-Separator"></span>
<h4 anchor="xaf-blazor-native-report-viewer">
<a name="xaf-blazor-native-report-viewer" class="anchor visible-anchor" href="#xaf-blazor-native-report-viewer">#</a>Migration to the Native Blazor Report Viewer
</h4>
<p> In v24.1, XAF's Blazor Reporting Module uses the native Report Viewer for Blazor Server apps
(<a href="https://docs.devexpress.com/XtraReports/403594/web-reporting/blazor-reporting/server/blazor-report-viewer-native" target="_blank" rel="noopener">DxReportViewer</a>) instead of a JavaScript-based Report Viewer
(<a href="https://docs.devexpress.com/XtraReports/DevExpress.Blazor.Reporting.DxDocumentViewer" target="_blank" rel="noopener">DxDocumentViewer</a>). </p>
<p> The native report viewer has a number of benefits for XAF Blazor developers: </p>
<ul>
<li>Support of Size Modes and all Blazor themes</li>
<li>Easier customization without JS using pure C#</li>
<li>Improved performance: Native implementation reduces load time and increases page navigation speed when compared to JavaScript wrapper based reporting tools.</li>
</ul>
<p><a href="https://supportcenter.devexpress.com/ticket/details/t1228848/reportsv2module-migration-from-dxdocumentviewer-to-dxreportviewer" target="_blank" rel="noopener">Breaking Change</a></p>
<p><a href="https://docs.devexpress.com/eXpressAppFramework/113591/shape-export-print-data/reports/reports-v2-module-overview?v=24.1" target="_blank" rel="noopener">Documentation</a></p> <span class="H-Separator"></span>
<h3 data-anchor="xaf-entity-framework" data-toc-title="Entity Framework">
<a name="xaf-entity-framework" class="anchor"></a>Entity Framework
</h3>
<h4 anchor="xaf-efcore-8-support">
<a name="xaf-efcore-8-support" class="anchor visible-anchor" href="#xaf-efcore-8-support">#</a>EF Core 8 ORM Support
</h4>
<p><a href="https://docs.devexpress.com/eXpressAppFramework/404215/debugging-testing-and-error-handling/code-diagnostics/xaf0026?v=24.1" target="_blank" rel="noopener">EF Core 8 support</a> officially ships in v24.1 for XAF and associated
Backend Web API Service. EF Core 8 is the latest production-ready version of Entity Framework. </p>
<p> While EF Core 8 offers numerous advantages over its predecessor (performance and customization included), it also introduced a series of breaking changes that we needed to address (for instance, DateOnly and TimeOnly support). </p>
<p> For more information about recent EF Core updates, refer to the following Microsoft documents: </p>
<ul>
<li><a href="https://learn.microsoft.com/en-us/ef/core/what-is-new/ef-core-8.0/whatsnew" target="_blank" rel="noopener">What's New in EF Core 8</a></li>
<li><a href="https://learn.microsoft.com/en-us/ef/core/what-is-new/ef-core-8.0/breaking-changes" target="_blank" rel="noopener">EF Core 8 Breaking Changes</a></li>
<li><a href="https://github.com/DevExpress-Examples/XAF_Security_E4908/tree/24.1.1%2B/Benchmarks" target="_blank" rel="noopener">Performance Benchmarks for EF Core 8 vs XPO ORM</a></li>
</ul> <span class="H-Separator"></span>
<h4 anchor="xaf-cascade-deletion-for-aggregated-one-to-many-collections-efcore">
<a name="xaf-cascade-deletion-for-aggregated-one-to-many-collections-efcore" class="anchor visible-anchor" href="#xaf-cascade-deletion-for-aggregated-one-to-many-collections-efcore">#</a>Cascade Deletion for Aggregated One-to-Many
Collections in EF Core
</h4>
<p> With v24.1, XAF's Solution Wizard includes <code data-renderer="hljs" class="csharp" data-control="Code-Inline">modelBuilder.SetOneToManyAssociationDeleteBehavior(DeleteBehavior.SetNull, DeleteBehavior.Cascade);</code> in the
OnModelCreating method of EF Core-based apps. This code will configure "DeleteBehavior.SetNull" for non-aggregated One-to-Many associations and "DeleteBehavior.Cascade" for aggregated One-to-Many associations respectively. Previously,
XAF's Aggregated attribute was not considered by EF Core as it was for XPO ORM (and there might be exceptions in certain ListView scenarios). </p>
<p>
<a href="https://docs.devexpress.com/eXpressAppFramework/402958/business-model-design-orm/business-model-design-with-entity-framework-core/relationships-between-entities-in-code-and-ui?v=24.1#one-to-many-behavior-on-delete" target="_blank" rel="noopener">Documentation</a>
</p> <span class="H-Separator"></span>
<h4 anchor="xaf-efcore-fixed-issues">
<a name="xaf-efcore-fixed-issues" class="anchor visible-anchor" href="#xaf-efcore-fixed-issues">#</a>Noteworthy EF Core-related Bug Fixes
</h4>
<p> In addition to new features, we also addressed the following issues in our v24.1 release cycle: </p>
<ul>
<li><a href="https://supportcenter.devexpress.com/ticket/details/T1217729/core-event-notifications-do-not-work-in-ef-core-applications" target="_blank" rel="noopener">T1217729</a> - Core – Scheduler Event notifications do not work in EF
Core applications</li>
<li><a href="https://supportcenter.devexpress.com/ticket/details/T1230436/core-properties-of-base-classes-that-are-not-included-in-ef-core-s-dbcontext-are-missing" target="_blank" rel="noopener">T1230436</a> - Core - Properties of base
classes not included in EF Core's DbContext are missing from the Application Model </li>
<li><a href="https://supportcenter.devexpress.com/ticket/details/T1219872/core-root-listview-in-the-instantfeedback-mode-doesn-t-update-the-modified-object-s-data" target="_blank" rel="noopener">T1219872</a> - Core - Root ListView in
the InstantFeedback mode doesn't update modified object data with EF Core </li>
<li><a href="https://supportcenter.devexpress.com/ticket/details/T1204704/winforms-column-header-filters-are-empty-for-reference-properties-with-ef-core" target="_blank" rel="noopener">T1204704</a> - WinForms - Column Header Filters are
empty for reference properties with EF Core </li>
</ul> <span class="H-Separator"></span>
<h3 data-anchor="xaf-security" data-toc-title="Security System">
<a name="xaf-security" class="anchor"></a>Security System
</h3>
<h4 anchor="xaf-sso-support">
<a name="xaf-sso-support" class="anchor visible-anchor" href="#xaf-sso-support">#</a>Single Sign-On Support
</h4>
<p> In v24.1, XAF Blazor and WinForms .NET 6+ apps support Single Sign-On (SSO) natively. Today, modern business apps are integrated with many external systems within organizations. For instance, if an organization uses Microsoft 365, XAF
apps are often available at <a href="https://myapps.microsoft.com/" target="_blank" rel="noopener">https://myapps.microsoft.com/</a> among many other apps within this organization. Since XAF Blazor and WinForms .NET 6+ apps (both XPO
and EF Core-based) support Microsoft Entra ID and other
<a href="https://docs.devexpress.com/eXpressAppFramework/404648/data-security-and-safety/security-system/authentication/oauth-and-custom-authentication" target="_blank" rel="noopener">OAuth2 providers</a>, organizations want/prefer XAF
apps to share the same login details or authentication cookies with existing systems/services such as
<a href="https://www.microsoft.com/en-us/security/business/identity-access/microsoft-entra-single-sign-on" target="_blank" rel="noopener">Microsoft Entra SSO</a>. </p>
<p> Said differently, organizations require the following: when a user is already authenticated within the organization (for instance, using Microsoft 365), XAF apps must seamlessly work with SSO. Previously, XAF developers had to
implement custom solutions to modify XAF’s login form and authentication behavior to support SSO. </p>
<p> Important SSO scenarios include, but are not limited to the following: </p>
<ul>
<li>
<p> If a user is NOT logged in within the organization, then XAF apps display a standard OAuth2/SSO provider logon form (just like Teams, Word or Outlook normally does for Microsoft 365). If a user was forced to sign out by
administrators, then XAF apps should display the standard logon form as well. </p>
</li>
<li>
<p> If a user is logged in within the organization (it can be another non-XAF app), then no XAF login form is displayed for the user and focus moves directly to the XAF app UI (by a link from an organization's `Apps dashboard` or via
other methods). The logon procedure in an XAF app proceeds automatically behind the scenes (via API calls). XAF users should NOT be forced to explicitly press the “Login with Microsoft” in this instance, because SSO will "just work"
as expected. </p>
</li>
</ul>
<p>
<a href="https://docs.devexpress.com/eXpressAppFramework/402197/data-security-and-safety/security-system/authentication/oauth-and-custom-authentication/active-directory-and-oauth2-authentication-providers-in-blazor-applications?v=24.1#automatic-login" target="_blank" rel="noopener">Documentation</a>
</p> <span class="H-Separator"></span>
<h4 anchor="xaf-bypass-security-pefmissions-checks">
<a name="xaf-bypass-security-pefmissions-checks" class="anchor visible-anchor" href="#xaf-bypass-security-pefmissions-checks">#</a>Bypass Security Permission Checks for Internal Business Logic
</h4>
<p> In addition, it is now possible to call the new
<a href="https://docs.devexpress.com/eXpressAppFramework/DevExpress.Persistent.BaseImpl.EF.BaseObject.SetPropertyValueWithSecurityBypass--1(System.String---0)?v=24.1" target="_blank" rel="noopener">SetPropertyValueWithSecurityBypass</a>
method from within your BaseObject descendants to bypass security checks for certain protected properties in your internal application logic (custom base classes are also supported). </p>
<p> This capability is especially valuable to XAF developers when you wish to set service properties like CreatedBy, ModifiedBy, CreatedOn, UpdatedOn, etc. - our Audit Trail and Model Difference modules operate using a similar mechanism.
The <code data-renderer="hljs" class="csharp" data-control="Code-Inline">SetPropertyValueWithBypassSecurity</code> method can freely set protected properties on behalf of a restricted/regular user in code much like an application
administrator - without having to know admin credentials (like impersonation for service tasks). </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">C#</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="csharp"><span class="hljs-function">ApplicationUser <span class="hljs-title">GetCurrentUser</span>()</span> {
<span class="hljs-keyword">return</span> ObjectSpace.GetObjectByKey<ApplicationUser>(
ObjectSpace.ServiceProvider.GetRequiredService<ISecurityStrategyBase>().UserId);
}
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">override</span> <span class="hljs-keyword">void</span> <span class="hljs-title">OnSaving</span>()</span> {
<span class="hljs-keyword">base</span>.OnSaving();
<span class="hljs-keyword">if</span> (ObjectSpace.IsNewObject(<span class="hljs-keyword">this</span>)) {
SetPropertyValueWithSecurityBypass(<span class="hljs-keyword">nameof</span>(CreatedBy), GetCurrentUser());
}
<span class="hljs-keyword">else</span> {
SetPropertyValueWithSecurityBypass(<span class="hljs-keyword">nameof</span>(UpdatedBy), GetCurrentUser());
SetPropertyValueWithSecurityBypass(<span class="hljs-keyword">nameof</span>(UpdatedOn), DateTime.Now);
}
}</code></pre>
</div>
</div>
<p> As you probably know, this is a
<a href="https://supportcenter.devexpress.com/ticket/details/q359904/securitystrategycomplex-how-to-modify-objects-properties-in-code-when-the-user-does-not" target="_blank" rel="noopener">long-requested option</a> for many XAFers - an
option that prevented full migration from Integrated Mode to Middle Tier Security (because
<a href="https://docs.devexpress.com/eXpressAppFramework/DevExpress.EntityFrameworkCore.Security.SecuredEFCoreObjectSpaceProvider-1.CreateNonsecuredObjectSpace?p=net6" target="_blank" rel="noopener">CreateNonsecuredObjectSpace</a> and
other workarounds were inconvenient). </p>
<p> The <code data-renderer="hljs" class="csharp" data-control="Code-Inline">SetPropertyValueWithBypassSecurity</code> also includes certain limitations like calling this method is only supported from inside <code data-renderer="hljs"
class="csharp" data-control="Code-Inline">BaseObject.OnSaving</code> (for the best security) or the bypassed property cannot update other protected properties internally. We are of the opinion that this new option will cover 80% of
popular use-cases. </p>
<p><a href="https://supportcenter.devexpress.com/ticket/details/t1215959/core-ixafentityobject-onsaving-method-is-now-called-on-the-server-side-when-ef-core-with" target="_blank" rel="noopener">Breaking Change</a></p> <span
class="H-Separator"></span>
<h4 anchor="xaf-performance-for-middle-tier-security-winforms">
<a name="xaf-performance-for-middle-tier-security-winforms" class="anchor visible-anchor" href="#xaf-performance-for-middle-tier-security-winforms">#</a>Enhanced Performance for Middle Tier Security for WinForms Apps
</h4>
<p> XAF WinForms with <a href="https://docs.devexpress.com/eXpressAppFramework/404389/data-security-and-safety/security-system/security-tiers/middle-tier-security-ef-core?v=24.1" target="_blank" rel="noopener">Middle Tier Security</a>
execute much faster in v24.1. We boosted performance for both EF Core 8 and XPO ORM, as compared to v23.2 (XPO ORM results are even better - a 2.5x improvement). The graphs below show the current duration of batch of performance tests
and also individual tests in 24.1 vs v23.2 for EF Core 8. </p>
<p><a href="https://supportcenter.devexpress.com/ticket/details/t1221083/core-the-client-server-communication-protocol-changed-to-websocket-in-net-6-applications" target="_blank" rel="noopener">Breaking Change</a></p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-xaf-performance-tests-for-middle-tier-security-winforms.png"
srcset="/subscriptions/i/24.1/24-1-xaf-performance-tests-for-middle-tier-security-winforms.png 1x, /subscriptions/i/24.1/24-1-xaf-performance-tests-for-middle-tier-security-winforms@2x.png 2x"
alt="Enhanced Performance for Middle Tier Security for WinForms Apps - XAF, DevExpress" width="781" height="327" style="border: none" id="ctl00_ctl00_Content_Content_ctl7789"></div> <span class="H-Separator"></span>
<h3 data-anchor="xaf-multi-tenancy" data-toc-title="Multi-Tenancy">
<a name="xaf-multi-tenancy" class="anchor"></a>Multi-Tenancy
</h3>
<h4 anchor="xaf-custom-fields-in-tenant-class">
<a name="xaf-custom-fields-in-tenant-class" class="anchor visible-anchor" href="#xaf-custom-fields-in-tenant-class">#</a>Extend the Built-in Tenant Class with Custom Fields
</h4>
<p> You can now extend the standard
<a href="https://docs.devexpress.com/eXpressAppFramework/404667/multitenancy/multitenant-application-artchitecture?v=24.1#extend-the-built-in-tenant-class-with-custom-fields" target="_blank" rel="noopener">Tenant</a> class to associate
additional data (for instance, module and feature license info) with tenants stored in the application’s Host Database. Of course, you can also access custom Tenant fields in code later (from a
<a href="https://docs.devexpress.com/eXpressAppFramework/404667/multitenancy/multitenant-application-artchitecture?v=24.1#access-custom-tenant-fields-in-code" target="_blank" rel="noopener">Controller</a> or
<a href="https://docs.devexpress.com/eXpressAppFramework/404667/multitenancy/multitenant-application-artchitecture?v=24.1#from-application-builders" target="_blank" rel="noopener">Application Builders</a>). We also supported this for
both EF Core and XPO ORM. </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">C#</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="csharp"><span class="hljs-comment">// MySolution.Module\BusinessObjects\CustomTenant.cs</span>
<span class="hljs-comment">// EF Core</span>
<span class="hljs-keyword">using</span> DevExpress.Persistent.BaseImpl.EF.MultiTenancy;
<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">CustomTenant</span> : <span class="hljs-title">Tenant</span> {
<span class="hljs-keyword">public</span> <span class="hljs-keyword">virtual</span> <span class="hljs-built_in">string</span> CustomField { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
}
<span class="hljs-comment">// MySolution.Blazor.Server/Startup.cs (MySolution.Win/Startup.cs)</span>
builder.AddMultiTenancy()
.WithCustomTenantType<CustomTenant>()
<span class="hljs-comment">//...</span></code></pre>
</div>
</div>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-xaf-custom-fields-in-tenant-class.png" alt="Enhanced Performance for Middle Tier Security for WinForms Apps - XAF, DevExpress" width="894" height="297" style="border: none"
id="ctl00_ctl00_Content_Content_ctl7811"></div> <span class="H-Separator"></span>
<h4 anchor="xaf-middle-tier-security-for-winforms">
<a name="xaf-middle-tier-security-for-winforms" class="anchor visible-anchor" href="#xaf-middle-tier-security-for-winforms">#</a>Middle Tier Security for WinForms Apps: Multi-Tenancy and OAuth2 Support
</h4>
<p> In v24.1, XAF WinForms apps (.NET 6+) with Middle Tier Security natively supports <a href="https://docs.devexpress.com/eXpressAppFramework/404436/multitenancy" target="_blank" rel="noopener">Multi-Tenancy</a> and
<a href="https://docs.devexpress.com/eXpressAppFramework/404648/data-security-and-safety/security-system/authentication/oauth-and-custom-authentication" target="_blank" rel="noopener">OAuth2 providers</a> (for example, Microsoft Entra
ID or Google). Our <a href="https://github.com/DevExpress-Examples/xaf-create-multitenant-application/tree/24.1.2%2B" target="_blank" rel="noopener">Outlook Inspired Demo</a> now also uses Middle Tier Security with the Multi-Tenancy
module. </p>
<p> As we described in our <a href="https://docs.devexpress.com/eXpressAppFramework/404691/security-considerations/general-security-considerations#data-store-protection" target="_blank" rel="noopener">Security Considerations</a> help
topic, Windows desktop apps can better meet enterprise security standards with our Middle Tier application server. With our solution, EF Core or XPO developers can retain their standard DbContext or Session and initiate remote
connections to a data store from any .NET client (like XAF WinForms or non-XAF apps). This capability is critical within certain environments/business apps (those that cannot maintain direct database connections because of security
considerations). </p>
<p> Non-XAF EF Core or XPO developers can benefit from our Middle Tier application server and preserve DbContext or Session with their entity data model
(<a href="https://docs.devexpress.com/eXpressAppFramework/404398/data-security-and-safety/security-system/security-tiers/middle-tier-security-ef-core/connect-to-the-efcore-middle-tier-service-from-non-xaf-applications" target="_blank" rel="noopener">learn more</a>).
<strong>This is especially critical for many desktop .NET developers (WinForms, WPF, WinUI, etc.), who are now required to meet higher security standards</strong>. In a nutshell, these developers need to either retrofit/modernize their
"fat clients" for Windows (#1) or redo everything from scratch using modern Web technologies and Cloud services (#2). Our Middle Tier Security allows you to choose the "easier" and potentially more reliable route (#1), and to "replace"
direct database connections with middleware. Review the following code snippet for more information in this regard: </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">C#</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="csharp"><span class="hljs-keyword">var</span> httpRemoteRepository = <span class="hljs-keyword">new</span> HttpRemoteRepository(httpClient, <span class="hljs-keyword">typeof</span>(EFCoreDbContext).FullName);
<span class="hljs-keyword">var</span> optionsBuilder = <span class="hljs-keyword">new</span> DbContextOptionsBuilder<EFCoreDbContext>();
optionsBuilder.UseMiddleTier(opt =>
opt.UseRemoteRepository(httpRemoteRepository));
optionsBuilder.UseChangeTrackingProxies();
optionsBuilder.UseLazyLoadingProxies();
<span class="hljs-keyword">var</span> dbContextOptions = optionsBuilder.Options;
<span class="hljs-keyword">var</span> dbContext = <span class="hljs-keyword">new</span> EFCoreDbContext(dbContextOptions);
<span class="hljs-keyword">var</span> users = dbContext.Employees.ToList();</code></pre>
</div>
</div> <span class="H-Separator"></span>
<h4 anchor="xaf-webapi">
<a name="xaf-webapi" class="anchor visible-anchor" href="#xaf-webapi">#</a>Web API Service for XAF & Non-XAF UI Clients (Powered by EF Core & XPO ORM)
</h4>
<p> In v24.1, our <a href="https://docs.devexpress.com/eXpressAppFramework/403394/backend-web-api-service" target="_blank" rel="noopener">Backend Web API Service</a> supports
<a href="https://docs.devexpress.com/eXpressAppFramework/404436/multitenancy" target="_blank" rel="noopener">Multi-Tenancy</a> for both EF Core and XPO ORM. </p>
<p> Our Web API Service has both <a href="/products/net/application_framework/security-web-api-service.xml">FREE (basic CRUD)</a> and
<a href="https://docs.devexpress.com/eXpressAppFramework/404176/backend-web-api-service/obtain-a-report-from-a-web-api-controller-endpoint" target="_blank" rel="noopener">paid features</a> (such as reporting, audit trail, validation,
file attachments, localization, etc). We also distribute many demo applications illustrating the use of free and paid APIs with
<a href="https://community.devexpress.com/blogs/news/archive/2023/03/29/authorize-ef-core-crud-operations-and-download-reports-in-net-maui-with-odata-web-api.aspx" target="_blank" rel="noopener">.NET MAUI</a>,
<a href="https://www.devexpress.com/go/XAF_Security_NonXAF_Blazor_WebAssembly.aspx" target="_blank" rel="noopener">Blazor WebAssembly</a>,
<a href="https://community.devexpress.com/blogs/news/archive/2023/04/11/consume-the-devexpress-backend-web-api-from-javascript-with-svelte-part-1.aspx" target="_blank" rel="noopener">JavaScript</a> and
<a href="https://go.devexpress.com/XAF_Security_NonXAF_Series.aspx" target="_blank" rel="noopener">even more</a> (for paid features, you must own a DevExpress Universal Subscription license). </p>
<p> To learn more about our Web API Service and determine whether it can be of value within your organization, please review the following blog post:
<a href="https://community.devexpress.com/blogs/news/archive/2022/10/17/common-questions-about-the-new-devexpress-web-api-service-powered-by-entity-framework-and-xpo-orm.aspx" target="_blank" rel="noopener">Common Questions about the New DevExpress Web API Service (powered by Entity Framework and XPO ORM)</a>.
</p> <span class="H-Separator"></span>
<h3 data-anchor="xaf-cross-platform" data-toc-title="Cross-Platform Enhancements">
<a name="xaf-cross-platform" class="anchor"></a>Cross-Platform Enhancements
</h3>
<h4 anchor="xaf-system-text-json">
<a name="xaf-system-text-json" class="anchor visible-anchor" href="#xaf-system-text-json">#</a>Migration from Newtonsoft.Json to System.Text.Json
</h4>
<p> "System.Text.Json" library is now used to deserialize input parameters for <a href="https://docs.devexpress.com/eXpressAppFramework/403394/backend-web-api-service" target="_blank" rel="noopener">Backend Web API Service</a> endpoints.
</p>
<p> For more information, refer to the following blog post:
<a href="https://community.devexpress.com/blogs/news/archive/2024/04/02/net-and-net-framework-migration-from-newtonsoft-json-to-system-text-json-v24-1.aspx" target="_blank" rel="noopener">.NET and .NET Framework — Migration from Newtonsoft.Json to System.Text.Json (v24.1)</a>.
</p>
<p><a href="https://supportcenter.devexpress.com/ticket/details/t1225165/xaf-system-text-json-library-is-used-to-deserialize-input-parameters-of-the-web-api" target="_blank" rel="noopener">Breaking Change</a></p> <span
class="H-Separator"></span>
<h4 anchor="xaf-dateonly-timeonly-support">
<a name="xaf-dateonly-timeonly-support" class="anchor visible-anchor" href="#xaf-dateonly-timeonly-support">#</a>Support of New .NET DateOnly and TimeOnly Types for EF Core 8 and Blazor/WinForms UI
</h4>
<p> As you probably read in the EF Core 8 breaking changes above,
<a href="https://learn.microsoft.com/en-us/ef/core/what-is-new/ef-core-8.0/breaking-changes#sqlserver-date-time-only" target="_blank" rel="noopener">SQL Server date and time now scaffold to .NET DateOnly and TimeOnly</a>, Grid List
Editor and associated Date/Time Property Editors in XAF Blazor and WinForms apps for .NET 6+ now support the new .NET types accordingly. </p>
<p> The underlying <a href="#blazor-grid-dateonly-timeonly-support">Blazor</a> and <a href="#winforms-dateonly-support">WinForms</a> grid components support operations with DateOnly/TimeOnly (sorting, grouping, filtering, including Filter
Editors auto filter rows, column header filters) - as will Criteria Language, Server Mode, and other underlying data access components for EF Core. </p> <span class="H-Separator"></span>
<h4 anchor="xaf-cli">
<a name="xaf-cli" class="anchor visible-anchor" href="#xaf-cli">#</a>Command Line Interface (CLI) Solution Wizard Templates
</h4>
<p> XAF v24.1 allows you to use the <a href="https://learn.microsoft.com/en-us/dotnet/core/tools/" target="_blank" rel="noopener">.NET command line interface (CLI)</a> or the `dotnet` tool to quickly create XAF Blazor and WinForms apps
from the console (without using XAF's Solution Wizard). This is similar to the DevExpress Reports implementation:
<a href="https://docs.devexpress.com/XtraReports/404160/web-reporting/blazor-reporting/get-started/use-cli-templates" target="_blank" rel="noopener">Use .NET CLI Templates</a>. </p>
<p> This capability is valuable for XAF developers using Microsoft Visual Studio Code (VS Code) or JetBrains Rider in both Windows and non-Windows development environments (like Linux or MacOS). Previously, these users had to first create
XAF projects in Visual Studio for Windows using the Solution Wizard. </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">CLI</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="csharp">dotnet <span class="hljs-keyword">new</span> install DevExpress.XAF.ProjectTemplates::<span class="hljs-number">24.1</span><span class="hljs-number">.3</span>
dotnet <span class="hljs-keyword">new</span> dx.xaf -p blazor win -e2e -api Standalone -s MiddleTier -n MyCoolApp
cd MyCoolApp
dotnet run</code></pre>
</div>
</div>
<p><a href="https://docs.devexpress.com/eXpressAppFramework/404967/installation-upgrade-version-history/dotnet-cli-integration?v=24.1" target="_blank" rel="noopener">Documentation</a></p> <span class="H-Separator"></span>
<h4 anchor="xaf-xpo-orm-data-model-wizard">
<a name="xaf-xpo-orm-data-model-wizard" class="anchor visible-anchor" href="#xaf-xpo-orm-data-model-wizard">#</a>XPO ORM Data Model Wizard — Trust Level Certificate and Encryption Options
</h4>
<div class="Attention">
<p class="sys-h-align-left"> Please note that the changes described below are already available in the latest update of our current major version: <strong>v23.2.5</strong>. </p>
</div>
<p> We enhanced the user experience in our <a href="https://docs.devexpress.com/XPO/14810/design-time-features/data-model-wizard?v=24.1" target="_blank" rel="noopener">Data Source Wizard</a> while binding a report to an instance of the MS
SQL Server. The data source connection screen now features two new options marked on the screenshot: </p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-xaf-xpo-data-source-wizard-encryption.png"
srcset="/subscriptions/i/24.1/24-1-xaf-xpo-data-source-wizard-encryption.png 1x, /subscriptions/i/24.1/24-1-xaf-xpo-data-source-wizard-encryption@2x.png 2x"
alt="XPO ORM Data Model Wizard — Trust Level Certificate and Encryption Options" width="769" height="761" style="border: none" id="ctl00_ctl00_Content_Content_ctl7960"></div>
<p> These new options/changes allow you to avoid the "<strong>The certificate chain was issued by an authority that is not trusted</strong>" error while binding a report to MS SQL Server database if you cannot set up MS SQL Server
differently. Learn more about this error and its cause in the following Microsoft topic:
<a href="https://learn.microsoft.com/en-us/troubleshoot/sql/database-engine/connect/certificate-chain-not-trusted?tabs=ole-db-driver-19" target="_blank" rel="noopener">The certificate chain was issued by an authority that isn't trusted - SQL Server (Microsoft Learn)</a>.
</p> <span class="H-Separator"></span>
<h3 data-anchor="xaf-survey" data-toc-title="Survey - XAF & Web API Service">
<a name="xaf-survey" class="anchor"></a>Survey - XAF & Web API Service
</h3>
<h4 anchor=""> Your Feedback Matters! </h4>
<div id="ctl00_ctl00_Content_Content_SurveyContainer" data-control="survey" class="InlineSurvey">
<div data-role="SurveyContent" data-markdown="false" data-partial="false" data-multiple-results="None" data-survey-id="539ce23c-e468-4bd6-aac8-49c9ab9197d3" data-auth-required="true"
data-user-data="{"IsLoggedIn":false,"IsEmployee":false,"CustomerId":null}" style="display: none;">
</div>
<div data-role="AuthRequired" style="display: block;"> Please <a href="https://www.devexpress.com/MyAccount/LogIn/?returnUrl=https%3a%2f%2fwww.devexpress.com%2fsubscriptions%2fwhats-new%2f">login</a> to complete the survey. </div>
<div data-role="Loading" style="display: none;">
<img src="../../Content/Editors/ajax-loader.gif" style="border-width:0px;">
</div>
<div data-role="Completed" style="display: none;">
<h3> Survey Completed </h3>
<p class="sys-max-width-md-80 sys-max-width-lg-60">Thank you for taking the time to complete this survey. Your responses have now been posted. If you want to follow up with additional information, feel free to send us an email at
<a href="mailto:clientservices@devexpress.com">clientservices@devexpress.com</a> anytime. </p>
</div>
<div data-role="AlreadyPassed" style="display: none;">
<h3> You've Already Completed This Survey </h3>
<p class="sys-max-width-md-80 sys-max-width-lg-60">Our records show that you have already completed this survey. If you want to follow up with additional information, send us an email at
<a href="mailto:clientservices@devexpress.com">clientservices@devexpress.com</a>.</p>
</div>
<div data-role="Expired" style="display: none;">
<h3> This survey has expired </h3>
<p>If you want to share your feedback or request new functionality, please submit a new support ticket via the <a href="https://supportcenter.devexpress.com/">DevExpress Support Center</a>. We’ll be happy to follow up.</p>
</div>
</div>
<h2 class="SectionHeader" data-anchor="coderush" data-toc-title="CodeRush">
<a data-whatsnew-platform="coderush" name="coderush" class="anchor"></a>CodeRush for Visual Studio v24.1
</h2>
<h3 data-anchor="cr-voice-support" data-toc-title="Voice Support">
<a name="cr-voice-support" class="anchor"></a>Voice Support
</h3>
<h4 anchor="">
</h4>
<p> After you specify Azure Speech Recognition and OpenAI API keys in
<a href="https://community.devexpress.com/blogs/markmiller/archive/2024/03/02/voice-setup-in-coderush-for-visual-studio.aspx" target="_blank" rel="noopener">Voice Setup</a>, you can enable voice features in Visual Studio 2022 and up.
</p> <p><img src="/subscriptions/i/24.1/24-1-coderush-left-right-ctrl-key-summary.jpg" alt="Voice Support - DevExpress CodeRush" width="658" height="287" style="border: none" id="ctl00_ctl00_Content_Content_ctl8158"></p> <p>
<a href="https://community.devexpress.com/blogs/markmiller/archive/2024/03/04/voice-setup-in-coderush-for-visual-studio.aspx" target="_blank" rel="noopener">Voice setup instructions</a></p> <span class="H-Separator"></span>
<h4 anchor="cr-voice-commands">
<a name="cr-voice-commands" class="anchor visible-anchor" href="#cr-voice-commands">#</a>Voice Commands
</h4>
<p> Hold <code data-renderer="hljs" class="csharp" data-control="Code-Inline">left Ctrl</code> key and speak to trigger
<a href="https://community.devexpress.com/blogs/markmiller/archive/2024/02/04/voice-commands-in-coderush-for-visual-studio.aspx" target="_blank" rel="noopener">voice commands</a>. Examples of things you can say and what they do: </p>
<ul>
<li>"open foo" - finds and opens Foo.cs file in editor</li>
<li>"class bar" - navigates to classes named "bar"</li>
<li>"bookmark storage" - creates a new bookmark named "storage"</li>
<li>"goto storage" - jumps to a bookmark named "storage"</li>
<li>"show me solution explorer" - shows the Solution Explorer</li>
<li>"line one hundred" - jumps to line 100 in current file</li>
</ul>
<p> Voice commands can use <strong>inferred intent</strong>, so you don't have to be precise when invoking them. Also, if you're working in large solutions (e.g., with 10,000+ files) the Voice Command for opening files is a huge
productivity boost. </p> <span class="H-Separator"></span>
<h4 anchor="cr-voice-to-code">
<a name="cr-voice-to-code" class="anchor visible-anchor" href="#cr-voice-to-code">#</a>Voice to Code
</h4>
<p> Hold <code data-renderer="hljs" class="csharp" data-control="Code-Inline">right Ctrl</code> and speak to dictate strings, comments, and expressions, and to name identifiers. Examples of what you can create with voice: </p>
<ul>
<li>A new PascalCase or camelCase identifier name when Visual Studio's <strong>Rename</strong> refactoring is active.</li>
<li><a href="https://community.devexpress.com/blogs/markmiller/archive/2024/03/04/string-dictation-in-coderush-for-visual-studio.aspx" target="_blank" rel="noopener">Dictated strings</a> (including expressions in interpolated strings).
</li>
<li><a href="https://community.devexpress.com/blogs/markmiller/archive/2024/03/04/comment-dictation-in-coderush-for-visual-studio.aspx" target="_blank" rel="noopener">Dictated comments</a> (including indentifier references in comments
and paramref and seealso tags in XML Doc comments)</li>
</ul>
<p>Expressions and statements:</p>
<ul>
<li><a href="https://community.devexpress.com/blogs/markmiller/archive/2024/03/04/voice-to-code-in-coderush-for-visual-studio.aspx" target="_blank" rel="noopener">Simple expressions</a>, like method and property calls, numbers and
binary expressions.</li>
<li><a href="https://community.devexpress.com/blogs/markmiller/archive/2024/06/05/voice-enhancements-in-coderush-for-visual-studio.aspx" target="_blank" rel="noopener">More advanced expressions</a>, like await expressions, null, true
and false literals, discards, method calls with out and ref arguments, and assignment statements.</li>
</ul> <span class="H-Separator"></span>
<h4 anchor="cr-voice-for-copilot">
<a name="cr-voice-for-copilot" class="anchor visible-anchor" href="#cr-voice-for-copilot">#</a>Voice for Copilot
</h4>
<p> Hold <code data-renderer="hljs" class="csharp" data-control="Code-Inline">left Ctrl</code> and speak "Hey Copilot!" followed by your query to interact with the
<a href="https://community.devexpress.com/blogs/markmiller/archive/2024/06/03/github-copilot-chat-voice-support-with-coderush-for-visual-studio.aspx" target="_blank" rel="noopener">GitHub Copilot Chat</a> tool window using your voice.
You can use words like "this method" or "this class" to automatically include relevant code in your query. If the Copilot tool window is already active and its <strong>chat prompt</strong> has focus, you can hold the <code
data-renderer="hljs" class="csharp" data-control="Code-Inline">right Ctrl</code> key down to directly dictate your query into the prompt control (there's no need to start your prompt with "Hey Copilot"). </p> <span
class="H-Separator"></span>
<h3 data-anchor="cr-navigation" data-toc-title="Navigation">
<a name="cr-navigation" class="anchor"></a>Navigation
</h3>
<h4 anchor="">
</h4>
<p> New quick navigation providers: </p>
<ul>
<li><strong>MEF Imports</strong> - find where the active type is imported.</li>
<li><strong>MEF Exports</strong> - find where the active type is exported.</li>
<li><strong>Type</strong> - go directly to the type of active variable or property.</li>
</ul> <span class="H-Separator"></span>
<h2 class="SectionHeader" data-anchor="vcl" data-toc-title="VCL">
<a data-whatsnew-platform="vcl" name="vcl" class="anchor"></a>VCL Controls v24.1
</h2>
<div class="WhatsNewTOC grid sys-visibility-hidden sys-visibility-hidden sys-visibility-sm-shown">
<div class="row">
<div class="col-sm-6 col-md-3 col-order-1">
<p><a href="#vcl-download"><span>Download Your Copy Today</span></a></p>
<p><a href="#vcl-rad-stydio-12-1"><span>RAD Studio 12.1 Support</span></a></p>
</div>
<div class="col-sm-6 col-md-3 col-sm-order-3 col-md-order-2">
<p><a href="#vcl-highdpi-support"><span>High DPI Support</span></a></p>
<p><a href="#vcl-data-aware-controls-and-menu"><span>Data-Aware Controls and Menu</span></a></p>
</div>
<div class="column-break sm">
</div>
<div class="col-sm-6 col-md-3 col-sm-order-2 col-md-order-3">
<p><a href="#vcl-ribbon"><span>Ribbon Control</span></a></p>
<p><a href="#vcl-chart"><span>Chart Control</span></a></p>
</div>
<div class="col-sm-6 col-md-3 col-order-4">
<p><a href="#vcl-survey"><span>Survey - VCL</span></a></p>
</div>
</div>
</div>
<h3 data-anchor="vcl-download" data-toc-title="Download Your Copy Today">
<a name="vcl-download" class="anchor"></a>Download Your Copy Today
</h3>
<p> Once you're ready to upgrade, simply login to the DevExpress Client Center and download the appropriate installer to proceed. </p> <p>
<a href="https://go.devexpress.com/DevExpressDownload_VCLTrial.aspx" target="_blank" rel="noopener" class="Button Orange">Download Free Trial (VCL)</a><a href="https://go.devexpress.com/DevExpressDownload_VCLDemos.aspx" target="_blank" rel="noopener" class="Button Gray">VCL Demos v24.1</a>
</p> <div class="Attention">
<p><strong>Your feedback matters.</strong><br> Please, review the description of <strong>VCL</strong>-related features below and leave your feedback at the end of the section. </p>
<p><a href="#vcl-survey">Go to the survey now.</a></p>
</div>
<h3 data-anchor="vcl-rad-stydio-12-1" data-toc-title="RAD Studio 12.1 Support">
<a name="vcl-rad-stydio-12-1" class="anchor"></a>RAD Studio 12.1 Support
</h3>
<p> DevExpress VCL v24.1 and v23.2.6+ officially support Delphi 12.1 and C++ Builder 12.1 (for both 32-bit and 64-bit). If you installed RAD Studio 12.1 previously, please apply its Patch 1, because it addresses the
<a href="https://embt.atlassian.net/servicedesk/customer/portal/1/RSS-536" target="_blank" rel="noopener">RSS-536</a> incompatibility issue for the Delphi 64-bit compiler
(<a href="https://community.devexpress.com/blogs/vcl/archive/2024/04/26/vcl-v23-2-support-for-rad-studio-12-1-athens-patch-1.aspx" target="_blank" rel="noopener">Blog Post</a>). Also, beware a
<a href="https://supportcenter.devexpress.com/ticket/details/t1231984/rich-edit-components-may-be-slower-due-to-changes-in-the-system-generics-defaults-unit" target="_blank" rel="noopener">known performance issue</a> in our Rich Text
Editor due to the System.Generics.Defaults unit changes. </p> <span class="H-Separator"></span>
<h3 data-anchor="vcl-highdpi-support" data-toc-title="High DPI Support">
<a name="vcl-highdpi-support" class="anchor"></a>High DPI Support
</h3>
<h4 anchor="vcl-vector-skin-support">
<a name="vcl-vector-skin-support" class="anchor visible-anchor" href="#vcl-vector-skin-support">#</a>Enhanced High DPI Resolution and Vector Skin/Image Support
</h4>
<p> In addition to new features, we also focus on
<a href="https://supportcenter.devexpress.com/versionhistory?platformsWithProducts=dee0f498-9b49-42c9-bee9-5530e0ea67f6&startBuildName=23.2.3&endBuildName=24.1.2&buildsMode=Range&hasPlatformsWithProducts=true" target="_blank" rel="noopener">bug fixes</a>,
especially for High DPI-related issues, vector skins, and performance bottlenecks. Ultimately, we want our VCL UI components to be polished, modern, and stand out among all competitors in these aspects (UI matters and <strong>this
affects almost every VCL customer</strong>). </p>
<p> Many "fixes" are technically "features". We've recently started to publish more bug reports (for instance, from our internal/private testing) and also include more information into all bug reports such as screenshots before/after and
samples - everybody can
<a href="https://supportcenter.devexpress.com/versionhistory?platformsWithProducts=dee0f498-9b49-42c9-bee9-5530e0ea67f6&startBuildName=23.2.3&endBuildName=24.1.2&buildsMode=Range&hasPlatformsWithProducts=true" target="_blank" rel="noopener">review this info</a>
and analyze the complexity of the work involved. </p> <span class="H-Separator"></span>
<h4 anchor="vcl-wxi-compact-skin">
<a name="vcl-wxi-compact-skin" class="anchor visible-anchor" href="#vcl-wxi-compact-skin">#</a>New Vector Theme - Windows 11 (WXI) Compact
</h4>
<p> We now ship our WXI Compact Skin - a clone of the WXI skin with smaller paddings and margins, which many of you were used to from traditional DevExpress VCL skins such as Bezier, Office, etc. </p> <p><img
src="/subscriptions/i/24.1/24-1-vcl-wxi-compact.png" srcset="/subscriptions/i/24.1/24-1-vcl-wxi-compact.png 1x, /subscriptions/i/24.1/24-1-vcl-wxi-compact@2x.png 2x" alt="Windows 11 (WXI) Compact Skin - VCL Components, DevExpress"
width="1111" height="812" style="border: none" id="ctl00_ctl00_Content_Content_ctl8389"></p>
<p> To enable the new WXI Compact Skin, assign <code data-renderer="hljs" class="csharp" data-control="Code-Inline">WXICompact</code> to the
<a href="https://docs.devexpress.com/VCL/dxSkinsForm.TdxSkinController?v=24.1" target="_blank" rel="noopener">TdxSkinController</a> component's
<a href="https://docs.devexpress.com/VCL/cxLookAndFeels.TcxLookAndFeelController.SkinName?v=24.1" target="_blank" rel="noopener">SkinName</a> property. </p> <p><img src="/subscriptions/i/24.1/24-1-vcl-enable-wxi-compact.png"
srcset="/subscriptions/i/24.1/24-1-vcl-enable-wxi-compact.png 1x, /subscriptions/i/24.1/24-1-vcl-enable-wxi-compact@2x.png 2x" alt="Enable the WXI Compact Skin in the Object Inspector - VCL Components, DevExpress" width="364"
height="449" style="border: none" id="ctl00_ctl00_Content_Content_ctl8402"></p> <span class="H-Separator"></span>
<h4 anchor="vcl-assign-svg-at-design-time">
<a name="vcl-assign-svg-at-design-time" class="anchor visible-anchor" href="#vcl-assign-svg-at-design-time">#</a>Easier SVG Assignment for Image Lists at Design-Time
</h4>
<p> In v24.1, the DevExpress VCL Ribbon (and other UI controls) allow you to use a single image list for large and small SVG icons. With this capability you can simply specify a small SVG icon and we will scale it up automatically (for
instance, in places where the control needs a large icon in the Ribbon). This will improve overall usability and should reduce time spent/maintenance in half. </p>
<p> Based on our roadmap survey votes, we made it possible for customers to use both old and new icon assignment strategies using
<a href="https://docs.devexpress.com/VCL/cxGraphics.TcxImageListSVGOptions.UseRegularAsLarge?v=24.1" target="_blank" rel="noopener">UseRegularAsLarge</a>,
<a href="https://docs.devexpress.com/VCL/cxGraphics.TcxImageListSVGOptions.LargeSize?v=24.1" target="_blank" rel="noopener">LargeSize</a> and related SVG image options. Existing apps and usage habits will remain unaffected. </p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-vcl-assign-svg-at-design-time.png" srcset="/subscriptions/i/24.1/24-1-vcl-assign-svg-at-design-time.png 1x, /subscriptions/i/24.1/24-1-vcl-assign-svg-at-design-time@2x.png 2x"
alt="Easier SVG Assignment for Image Lists at Design-Time - VCL Components, DevExpress" width="564" height="494" style="border: none" id="ctl00_ctl00_Content_Content_ctl8419"></div> <span class="H-Separator"></span>
<h4 anchor="vcl-wizards-for-layout-and-image-customization">
<a name="vcl-wizards-for-layout-and-image-customization" class="anchor visible-anchor" href="#vcl-wizards-for-layout-and-image-customization">#</a>Layout and Image Modifications in Design-Time Wizards and Dialogs
</h4>
<p> VCL v24.1 includes dozens of layout and `raster to vector` image adjustments in key <strong>design-time</strong> areas (wizards, designers, and dialogs). High DPI support is crucial and we want to set the highest standards in this
regard (in terms of developer usability and speed). </p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-vcl-customize-svg-images-at-design-time.png"
srcset="/subscriptions/i/24.1/24-1-vcl-customize-svg-images-at-design-time.png 1x, /subscriptions/i/24.1/24-1-vcl-customize-svg-images-at-design-time@2x.png 2x"
alt="Layout and Image Modifications in Design-Time Wizards and Dialogs - VCL Components, DevExpress" width="845" height="606" style="border: none" id="ctl00_ctl00_Content_Content_ctl8431"></div> <span class="H-Separator"></span>
<h3 data-anchor="vcl-data-aware-controls-and-menu" data-toc-title="Data-Aware Controls and Menu">
<a name="vcl-data-aware-controls-and-menu" class="anchor"></a>Data-Aware Controls and Menu
</h3>
<h4 anchor="vcl-accessibility">
<a name="vcl-accessibility" class="anchor visible-anchor" href="#vcl-accessibility">#</a>Accessibility Enhancements and Keyboard Support
</h4>
<p> Previous versions of the DevExpress ExpressBars and ExpressNavBar Suite included
<a href="https://docs.devexpress.com/VCL/405004/ExpressCrossPlatformLibrary/accessibility-support?v=24.1" target="_blank" rel="noopener">partial accessibility support</a> (powered by Microsoft Active Accessibility or
<a href="https://learn.microsoft.com/en-us/windows/win32/winauto/microsoft-active-accessibility" target="_blank" rel="noopener">MSAA</a>). We initially hoped to use MSAA to support remaining VCL controls, but research showed that it is
not technically feasible. It turned out that this COM-based technology is outdated for modern accessibility requirements and highly interactive UI controls like ours. </p>
<p> Accordingly, we built a new engine for ongoing accessibility-related enhancements (it is powered by Microsoft UI Automation or
<a href="https://docs.microsoft.com/en-us/dotnet/framework/ui-automation/ui-automation-overview" target="_blank" rel="noopener">UIA</a> - used in DevExpress WinForms and WPF products). UIA gave us much more flexibility and allowed to
introduce the following accessibility-related v24.1 features: </p>
<ul>
<li>UIA-powered controls now include Automation options like Name, Description, etc.</li>
<li>UIA-powered controls now include specialized events to customize Automation options at runtime.</li>
<li>UIA-powered controls currently include Button, Check Box, Radio Button, Group Box, Panel, Text Editor, Button Editor, and Label.</li>
</ul>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-vcl-accessibility.png" srcset="/subscriptions/i/24.1/24-1-vcl-accessibility.png 1x, /subscriptions/i/24.1/24-1-vcl-accessibility@2x.png 2x"
alt="Accessibility Enhancements - VCL Components, DevExpress" width="383" height="447" style="border: none" id="ctl00_ctl00_Content_Content_ctl8455"></div>
<p> Our effort in this regard work will continue throughout 2024-2025, and will include enhancements for key unsupported components: </p>
<ul>
<li>Data grid (key navigation and "read-only" scenarios, likely without data editing and other complex interactions in the first release)</li>
<li>Form layout manager (including layout groups, tabs, etc.)</li>
<li>Navigation and menu (key scenarios in both Ribbon and standard toolbars)</li>
<li>TreeList, Scheduler, Pivot Grid, and other popular data editors (key scenarios in both in-place and standalone editors)</li>
</ul>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-vcl-accessibility-2.png" srcset="/subscriptions/i/24.1/24-1-vcl-accessibility-2.png 1x, /subscriptions/i/24.1/24-1-vcl-accessibility-2@2x.png 2x"
alt="Accessibility Enhancements - VCL Components, DevExpress" width="364" height="447" style="border: none" id="ctl00_ctl00_Content_Content_ctl8459"></div> <span class="H-Separator"></span>
<h4 anchor="vcl-accent-insensitive-operation">
<a name="vcl-accent-insensitive-operation" class="anchor visible-anchor" href="#vcl-accent-insensitive-operation">#</a>Accent-Insensitive Operation Support for Data-Aware Controls
</h4>
<p> With v24.1, you can configure how various diacritic glyphs in letters (umlauts, grave, acute, and other accents) are treated. For instance, if you type "Joao" in a search box, Data Grid filtering results will include data records with
both "João" and "Joao". For more information, read the following quote from <a href="https://en.wikipedia.org/wiki/Diacritic" target="_blank" rel="noopener">Wikipedia</a>: </p>
<div class="Attention">
<p class="sys-h-align-left"> A <strong>diacritic</strong> (also diacritical mark, diacritical point, diacritical sign, or accent) is a glyph added to a letter or to a basic glyph. The term derives from the Ancient Greek διακριτικός
(diakritikós, "distinguishing"), from διακρίνω (diakrī́nō, "to distinguish"). The word diacritic is a noun, though it is sometimes used in an attributive sense, whereas diacritical is only an adjective. Some diacritics, such as the
acute ⟨á⟩, grave ⟨à⟩, and circumflex ⟨â⟩ (all shown above an 'a'), are often called accents. Diacritics may appear above or below a letter or in some other position such as within the letter or between two letters. </p>
</div>
<p> You can enable or configure accent-insensitive operations globally using the <a href="https://docs.devexpress.com/VCL/dxCore.TdxDiacriticStringOptions?v=24.1" target="_blank" rel="noopener">TdxDiacriticStringOptions</a> class: </p>
<ul>
<li><a href="https://docs.devexpress.com/VCL/dxCore.TdxDiacriticStringOptions.ComparisonMode?v=24.1" target="_blank" rel="noopener">ComparisonMode</a>: allows you to switch between comparison modes (Auto, Sensitive, Insensitive). By
default (Sensitive), we do not ignore accents. Insensitive mode can be of value for global organizations with users from different countries/data (for instance, names of employees or goods can be in different languages). </li>
<li><a href="https://docs.devexpress.com/VCL/dxCore.TdxDiacriticStringOptions.NormalizationMode?v=24.1" target="_blank" rel="noopener">NormalizationMode</a>: specifies the string normalization algorithm (Fast, System) used for string
comparison in diacritic-insensitive mode. The default algorithm (Fast) works up to 3 times faster compared to the operating system-dependent algorithm (System). </li>
</ul>
<p><strong>Note</strong>: <code data-renderer="hljs" class="csharp" data-control="Code-Inline">TdxDiacriticStringOptions</code> does not work in Server Mode – use database collation options instead. </p>
<p> Impacted text-comparison operations and control features include: </p>
<ul>
<li>Sorting</li>
<li>Grouping</li>
<li>Incremental search</li>
<li>Auto-filter row</li>
<li>Find panel, etc.</li>
</ul>
<p> This behavior expands to the following controls: </p>
<ul>
<li>Navigation control</li>
<li>Ribbon and standard toolbars</li>
<li>Lookup editors</li>
<li>Data grid</li>
<li>Pivot grid</li>
<li>Tree list</li>
<li>Other data-bound controls (powered by our Data Controller).</li>
</ul> <span class="H-Separator"></span>
<h4 anchor="vcl-edit-images">
<a name="vcl-edit-images" class="anchor visible-anchor" href="#vcl-edit-images">#</a>Editing Operations (Rotate, Crop, Flip, etc.) in Image Controls
</h4>
<p> You can now invoke the <a href="https://docs.devexpress.com/VCL/dxImageEditorDialog.dxShowImageEditor(337F7AF5)?v=24.1" target="_blank" rel="noopener">Image Editor dialog</a> for
<a href="https://docs.devexpress.com/VCL/cxImage.TcxImage?v=24.1" target="_blank" rel="noopener">TcxImage</a> and <a href="https://docs.devexpress.com/VCL/cxDBEdit.TcxDBImage?v=24.1" target="_blank" rel="noopener">TcxDBImage</a>
components using the Edit context menu command. Our design-time Image Picker dialog includes the new Edit command as well. The Edit command unlocks basic image editing operations: </p>
<ul>
<li>Crop and straighten</li>
<li>Adjust brightness, contrast and saturation</li>
<li>Mirror</li>
<li>Rotate, etc.</li>
</ul>
<p> The Image Editor maintains operation history and offers both undo and redo functionality. Once the editor is closed and changes are saved, modifications cannot be undone. </p>
<div class="Gallery">
<h6 class="Title"> VCL ImageEdit with Integrated Image Editor </h6>
<div class="tns-outer" id="tns1-ow">
<div class="tns-controls" aria-label="Carousel Navigation" tabindex="0"><button type="button" data-controls="prev" tabindex="-1" aria-controls="tns1"></button><button type="button" data-controls="next" tabindex="-1"
aria-controls="tns1"></button></div>
<div class="tns-liveregion tns-visually-hidden" aria-live="polite" aria-atomic="true">slide <span class="current">3</span> of 2</div>
<div id="tns1-mw" class="tns-ovh">
<div class="tns-inner" id="tns1-iw">
<div class="tns tns-slider tns-carousel tns-subpixel tns-calc tns-horizontal" data-show-dots="true" data-show-nav="true" data-centered="true" data-items="1" data-item-space="80" data-looped="true" id="tns1"
style="transition-duration: 0s; transform: translate3d(-33.3333%, 0px, 0px);">
<div class="tns-item tns-slide-cloned" aria-hidden="true" tabindex="-1">
<img src="/subscriptions/i/24.1/24-1-vcl-image-editor-1.png" srcset="/subscriptions/i/24.1/24-1-vcl-image-editor-1.png 1x, /subscriptions/i/24.1/24-1-vcl-image-editor-1@2x.png 2x" alt="" width="1018" height="657"
style="border: none" id="ctl00_ctl00_Content_Content_ctl8759">
</div>
<div class="tns-item tns-slide-cloned" aria-hidden="true" tabindex="-1">
<img src="/subscriptions/i/24.1/24-1-vcl-image-editor-2.png" srcset="/subscriptions/i/24.1/24-1-vcl-image-editor-2.png 1x, /subscriptions/i/24.1/24-1-vcl-image-editor-2@2x.png 2x" alt="" width="1018" height="657"
style="border: none" id="ctl00_ctl00_Content_Content_ctl8761">
</div>
<div class="tns-item tns-slide-active" id="tns1-item0">
<img src="/subscriptions/i/24.1/24-1-vcl-image-editor-1.png" srcset="/subscriptions/i/24.1/24-1-vcl-image-editor-1.png 1x, /subscriptions/i/24.1/24-1-vcl-image-editor-1@2x.png 2x" alt="" width="1018" height="657"
style="border: none" id="ctl00_ctl00_Content_Content_ctl8759">
</div>
<div class="tns-item" id="tns1-item1" aria-hidden="true" tabindex="-1">
<img src="/subscriptions/i/24.1/24-1-vcl-image-editor-2.png" srcset="/subscriptions/i/24.1/24-1-vcl-image-editor-2.png 1x, /subscriptions/i/24.1/24-1-vcl-image-editor-2@2x.png 2x" alt="" width="1018" height="657"
style="border: none" id="ctl00_ctl00_Content_Content_ctl8761">
</div>
<div class="tns-item tns-slide-cloned" aria-hidden="true" tabindex="-1">
<img src="/subscriptions/i/24.1/24-1-vcl-image-editor-1.png" srcset="/subscriptions/i/24.1/24-1-vcl-image-editor-1.png 1x, /subscriptions/i/24.1/24-1-vcl-image-editor-1@2x.png 2x" alt="" width="1018" height="657"
style="border: none" id="ctl00_ctl00_Content_Content_ctl8759">
</div>
<div class="tns-item tns-slide-cloned" aria-hidden="true" tabindex="-1">
<img src="/subscriptions/i/24.1/24-1-vcl-image-editor-2.png" srcset="/subscriptions/i/24.1/24-1-vcl-image-editor-2.png 1x, /subscriptions/i/24.1/24-1-vcl-image-editor-2@2x.png 2x" alt="" width="1018" height="657"
style="border: none" id="ctl00_ctl00_Content_Content_ctl8761">
</div>
</div>
</div>
</div>
<div class="tns-nav" aria-label="Carousel Pagination"><button type="button" data-nav="0" aria-controls="tns1" style="" aria-label="Carousel Page 1 (Current Slide)" class="tns-nav-active"></button><button type="button" data-nav="1"
tabindex="-1" aria-controls="tns1" style="" aria-label="Carousel Page 2"></button></div>
</div>
</div> <span class="H-Separator"></span>
<h4 anchor="vcl-exif-support">
<a name="vcl-exif-support" class="anchor visible-anchor" href="#vcl-exif-support">#</a>EXIF Metadata Support in Image Controls
</h4>
<p> In v24.1, our image controls (<code data-renderer="hljs" class="csharp" data-control="Code-Inline">TcxImage</code> and <code data-renderer="hljs" class="csharp" data-control="Code-Inline">TcxDbImage</code>) read and interpret EXIF
metadata from images and modify the image display accordingly. For instance, our image controls automatically rotate the image based on orientation metadata (unlike the standard TImage control and certain image viewers). </p>
<p> Impacted image-based scenarios (where rotation will take place) include: </p>
<ul>
<li>Data Grid cells</li>
<li>TreeList cells</li>
<li>Vertical and Property Grid cells</li>
</ul>
<p> Previously, this required a complex custom solution with a manual call of the Rotate method. Customers who implemented custom solutions on their own (for instance, image rotation in the grid or standalone image editors), can disable
this default behavior using a static feature toggle. The
<a href="https://docs.devexpress.com/VCL/dxGDIPlusClasses.TdxGPImage.DefaultImageExifAutoRotation?v=24.1" target="_blank" rel="noopener">TdxGPImage.DefaultImageExifAutoRotation</a> class property value defines if the image editor
rotates an image based on EXIF metadata. </p> <span class="H-Separator"></span>
<h4 anchor="vcl-field-name-based-expressions">
<a name="vcl-field-name-based-expressions" class="anchor visible-anchor" href="#vcl-field-name-based-expressions">#</a>Field Name-Based Expressions for Data-Aware Controls
</h4>
<p> With v24.1, you can use <code data-renderer="hljs" class="csharp" data-control="Code-Inline">{FieldName}</code> in
<a href="https://docs.devexpress.com/VCL/168035/ExpressSpreadSheet/concepts/formula-expressions/built-in-operators-and-functions" target="_blank" rel="noopener">formula expressions</a> in conditional formatting rules to refer to a field
by underlying name instead of a display name. Previously, you could only use a display name/caption or an index. This capability will help you create formulas for conditional formatting rules. </p>
<p> This is helpful in VCL apps that support multiple languages or other scenarios where you cannot rely on a field caption (due to its dynamic nature such as translation to another language). </p>
<p> Review expression syntax examples for conditional formatting expressions in our
<a href="https://docs.devexpress.com/VCL/404973/ExpressSpreadSheet/shared-libraries/conditional-formatting?v=24.1" target="_blank" rel="noopener">Online Documentation</a>. </p> <span class="H-Separator"></span>
<h3 data-anchor="vcl-ribbon" data-toc-title="Ribbon Control">
<a name="vcl-ribbon" class="anchor"></a>Ribbon Control
</h3>
<h4 anchor="vcl-ribbon-office365-style">
<a name="vcl-ribbon-office365-style" class="anchor visible-anchor" href="#vcl-ribbon-office365-style">#</a>Office 365 Style for VCL Ribbon Control
</h4>
<p> Our VCL Ribbon Control ships with a new Office 365 <a href="https://docs.devexpress.com/VCL/dxRibbon.TdxCustomRibbon.Style?v=24.1" target="_blank" rel="noopener">rendering style</a>. When our new Office 365 style is used, the Ribbon
control displays a Search box at the top of the Ribbon form and Show Ribbon options on the bottom right of the Ribbon UI. </p>
<p><img src="/subscriptions/i/24.1/24-1-vcl-ribbon-office365-style.png" srcset="/subscriptions/i/24.1/24-1-vcl-ribbon-office365-style.png 1x, /subscriptions/i/24.1/24-1-vcl-ribbon-office365-style@2x.png 2x"
alt="Office 365 Style for VCL Ribbon Control, DevExpress" width="1052" height="441" style="border: none" id="ctl00_ctl00_Content_Content_ctl8571"></p> <span class="H-Separator"></span>
<h3 data-anchor="vcl-chart" data-toc-title="Chart Control">
<a name="vcl-chart" class="anchor"></a>Chart Control
</h3>
<h4 anchor="vcl-chart-secondary-axis">
<a name="vcl-chart-secondary-axis" class="anchor visible-anchor" href="#vcl-chart-secondary-axis">#</a>Secondary Axes
</h4>
<p> Secondary axes can be of value if you need to display multiple scales with different measurement units. You can now use
<a href="https://docs.devexpress.com/VCL/dxChartXYDiagram.TdxChartSecondaryAxes.AxesX?v=24.1" target="_blank" rel="noopener">SecondaryAxes.AxesX</a> and
<a href="https://docs.devexpress.com/VCL/dxChartXYDiagram.TdxChartSecondaryAxes.AxesY?v=24.1" target="_blank" rel="noopener">SecondaryAxes.AxesY</a> properties to add and configure supplemental axes for the main axis of arguments
(X-axis) and main axis of values (Y-axis). </p>
<p> The following code snippet creates a secondary axis of values and associates it with the first series in an XY diagram. Refer to the
<a href="https://docs.devexpress.com/VCL/dxChartXYDiagram.TdxChartSecondaryAxes?v=24.1" target="_blank" rel="noopener">TdxChartSecondaryAxes</a> class description for detailed information on available options. </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">Delphi</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="Delphi"><span class="hljs-keyword">var</span>
ADiagram: TdxChartXYDiagram;
AAxisY: TdxChartSecondaryAxisYCollectionItem;
AXYSeries: TdxChartXYSeries;
<span class="hljs-keyword">begin</span>
<span class="hljs-keyword">if</span> dxChartControl1.DiagramCount = <span class="hljs-number">0</span> <span class="hljs-keyword">then</span> <span class="hljs-keyword">Exit</span>;
ADiagram := dxChartControl1.Diagrams[<span class="hljs-number">0</span>] <span class="hljs-keyword">as</span> TdxChartXYDiagram;
<span class="hljs-keyword">if</span> ADiagram.SeriesCount = <span class="hljs-number">0</span> <span class="hljs-keyword">then</span> <span class="hljs-keyword">Exit</span>;
ASeries := ADiagram.Series[<span class="hljs-number">0</span>];
AAxisY := ADiagram.SecondaryAxes.AxesY.Add;
ASeries.View.AxisY := AAxisY.Axis;
AAxisY.Title.Text := <span class="hljs-string">'Income (USD)'</span>;
AAxisY.Title.Alignment := TdxAlignment.Center;
AAxisY.Appearance.Color := TdxAlphaColors.Gray;
<span class="hljs-keyword">end</span>;</code></pre>
</div>
</div>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-vcl-chart-secondary-axes.png" srcset="/subscriptions/i/24.1/24-1-vcl-chart-secondary-axes.png 1x, /subscriptions/i/24.1/24-1-vcl-chart-secondary-axes@2x.png 2x"
alt="Secondary Axes - VCL Chart Control, DevExpress" width="688" height="407" style="border: none" id="ctl00_ctl00_Content_Content_ctl8595"></div> <span class="H-Separator"></span>
<h4 anchor="vcl-chart-locarithmic-scale">
<a name="vcl-chart-locarithmic-scale" class="anchor visible-anchor" href="#vcl-chart-locarithmic-scale">#</a>Logarithmic Scales
</h4>
<p> A logarithmic scale can be of value when you need to display a value range that differs by large orders of magnitude. You can now set the
<a href="https://docs.devexpress.com/VCL/dxChartXYDiagram.TdxChartCustomAxis.Logarithmic?v=24.1" target="_blank" rel="noopener">Logarithmic</a> property to True or False to switch between logarithmic and standard numeric scales for the
axis (<a href="https://docs.devexpress.com/VCL/dxChartXYDiagram.TdxChartCustomAxis?v=24.1" target="_blank" rel="noopener">TdxChartCustomAxis</a>). The
<a href="https://docs.devexpress.com/VCL/dxChartXYDiagram.TdxChartCustomAxis.LogarithmicBase?v=24.1" target="_blank" rel="noopener">LogarithmicBase</a> property helps you specify the base of the logarithm (for the logarithmic scale of
the axis - default is 10). </p>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-vcl-chart-logarithmic-scale.png" srcset="/subscriptions/i/24.1/24-1-vcl-chart-logarithmic-scale.png 1x, /subscriptions/i/24.1/24-1-vcl-chart-logarithmic-scale@2x.png 2x"
alt="Logarithmic Scales - VCL Chart Control, DevExpress" width="836" height="716" style="border: none" id="ctl00_ctl00_Content_Content_ctl8613"></div> <span class="H-Separator"></span>
<h4 anchor="vcl-chart-point-segment-color-colorization">
<a name="vcl-chart-point-segment-color-colorization" class="anchor visible-anchor" href="#vcl-chart-point-segment-color-colorization">#</a>Point and Segment Color Customization via Events
</h4>
<p> You can handle <a href="https://docs.devexpress.com/VCL/dxChartPalette.TdxChartPalette.GetColorsForIndex(System.Integer)?v=24.1#code-example" target="_blank" rel="noopener">OnGetSeriesPointDrawParameters</a> and
<a href="https://docs.devexpress.com/VCL/dxChartCore.TdxChartCustomDiagram.OnGetValueLabelDrawParameters?v=24.1" target="_blank" rel="noopener">OnGetValueLabelDrawParameters</a> events to customize individual series points and
associated value labels based on specific conditions. </p>
<p><strong>Example #1</strong>: Generate unique fill colors for all point markers in the series (Europe's population).</p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">Delphi</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="Delphi"><span class="hljs-function"><span class="hljs-keyword">procedure</span> <span class="hljs-title">TFeaturesDemoMainForm</span>.<span class="hljs-title">cdLineGetSeriesPointDrawParameters</span><span class="hljs-params">(
Sender: TdxChartCustomDiagram;
AArgs: TdxChartGetSeriesPointDrawParametersEventArgs)</span>;</span>
<span class="hljs-keyword">var</span>
ALineDrawParameters: TdxChartLineSeriesPointDrawParameters;
APalette: TdxChartPalette;
APaletteItem: TdxChartPaletteItem;
<span class="hljs-keyword">begin</span>
APalette := TdxChartStandardPaletteRepository.FindPalette(<span class="hljs-string">'Slipstream'</span>);
<span class="hljs-keyword">if</span> AArgs.SeriesPoint.Series.Caption = <span class="hljs-string">'Europe'</span> <span class="hljs-keyword">then</span>
<span class="hljs-keyword">begin</span>
<span class="hljs-keyword">if</span> AArgs.DrawParameters.ClassType <> TdxChartLineSeriesPointDrawParameters <span class="hljs-keyword">then</span> <span class="hljs-keyword">Exit</span>;
ALineDrawParameters := AArgs.DrawParameters <span class="hljs-keyword">as</span> TdxChartLineSeriesPointDrawParameters;
APaletteItem := APalette.GetColorsForIndex(AArgs.SeriesPoint.<span class="hljs-keyword">Index</span>);
ALineDrawParameters.MarkerAppearance.FillOptions.Color := APaletteItem.Color;
<span class="hljs-keyword">end</span>;
<span class="hljs-keyword">end</span>;</code></pre>
</div>
</div>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-vcl-chart-example-1.png" srcset="/subscriptions/i/24.1/24-1-vcl-chart-example-1.png 1x, /subscriptions/i/24.1/24-1-vcl-chart-example-1@2x.png 2x"
alt="Generate unique fill colors for all point markers in the series" width="651" height="363" style="border: none" id="ctl00_ctl00_Content_Content_ctl8633"></div>
<p><strong>Example #2</strong>: Display different measurement units for value labels (millions or thousands of $). </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">Delphi</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="Delphi"><span class="hljs-function"><span class="hljs-keyword">procedure</span> <span class="hljs-title">TMyForm</span>.<span class="hljs-title">cdAreaGetValueLabelDrawParameters</span><span class="hljs-params">(Sender: TdxChartCustomDiagram;
AArgs: TdxChartGetValueLabelDrawParametersEventArgs)</span>;</span>
<span class="hljs-keyword">begin</span>
<span class="hljs-keyword">if</span> AArgs.SeriesPoint.Value >= <span class="hljs-number">1000</span> * <span class="hljs-number">1000</span> <span class="hljs-keyword">then</span> <span class="hljs-comment">// Millions</span>
AArgs.Text := Format(<span class="hljs-string">'%.1fM'</span>, [AArgs.SeriesPoint.Value / (<span class="hljs-number">1000</span> * <span class="hljs-number">1000</span>)])
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> AArgs.SeriesPoint.Value >= <span class="hljs-number">1000</span> <span class="hljs-keyword">then</span> <span class="hljs-comment">// Thousands</span>
AArgs.Text := Format(<span class="hljs-string">'%.0fk'</span>, [AArgs.SeriesPoint.Value / <span class="hljs-number">1000</span>])
<span class="hljs-keyword">else</span>
AArgs.Text := Format(<span class="hljs-string">'%0f'</span>, [AArgs.SeriesPoint.Value]);
<span class="hljs-keyword">end</span>;</code></pre>
</div>
</div>
<div class="small-image"><img src="/subscriptions/i/24.1/24-1-vcl-chart-example-2.png" srcset="/subscriptions/i/24.1/24-1-vcl-chart-example-2.png 1x, /subscriptions/i/24.1/24-1-vcl-chart-example-2@2x.png 2x"
alt="Display different measurement units for value labels" width="784" height="602" style="border: none" id="ctl00_ctl00_Content_Content_ctl8639"></div>
<p> Review more code examples for Area, Line, Bar, Pie chart views in our
<a href="https://docs.devexpress.com/VCL/dxChartCore.TdxChartCustomDiagram.OnGetSeriesPointDrawParameters?v=24.1" target="_blank" rel="noopener">Online Documentation</a>. </p> <span class="H-Separator"></span>
<h4 anchor="vcl-chart-palettes">
<a name="vcl-chart-palettes" class="anchor visible-anchor" href="#vcl-chart-palettes">#</a>Palettes
</h4>
<p> You can now use the <a href="https://docs.devexpress.com/VCL/dxChartControl.TdxCustomChartControl.Palette?v=24.1" target="_blank" rel="noopener">Palette</a> property to switch between
<a href="https://docs.devexpress.com/VCL/dxChartPalette.TdxChartPalette?v=24.1" target="_blank" rel="noopener">color palettes</a> whose color sets are applied to individual simple series values and XY series. The following code snippet
applies a predefined palette ("Nature Colors") to the chart control: </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">Delphi</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="Delphi">dxChartControl1.Palette := TdxChartStandardPaletteRepository.FindPalette(<span class="hljs-string">'Nature Colors'</span>);</code></pre>
</div>
</div>
<p> You can also add a <a href="https://docs.devexpress.com/VCL/dxChartPalette.TdxChartPaletteRepository?v=24.1" target="_blank" rel="noopener">TdxChartPaletteRepository</a> component to create and manage
<a href="https://docs.devexpress.com/VCL/dxChartPalette.TdxChartUserPalette?v=24.1" target="_blank" rel="noopener">custom palettes</a>. The following code snippet creates a user palette with three colors and applies the palette to the
chart control: </p>
<div data-control="Code" class="Code CodeNew">
<ul>
<li class="Active">Delphi</li>
</ul>
<div class="CodeContainer Active">
<pre><code data-renderer="hljs" class="Delphi"><span class="hljs-keyword">var</span>
AChartPalette: TdxChartUserPalette;
<span class="hljs-keyword">begin</span>
AChartPalette := dxChartPaletteRepository1.CreateItem;
AChartPalette.<span class="hljs-keyword">Name</span> := <span class="hljs-string">'My Palette 1'</span>; <span class="hljs-comment">// Assigns a unique palette name</span>
AChartPalette.Count := <span class="hljs-number">3</span>; <span class="hljs-comment">// Sets the size of the palette item array</span>
AChartPalette.Items[<span class="hljs-number">0</span>] := TdxChartPaletteItem.Create(TdxAlphaColors.Red);
AChartPalette.Items[<span class="hljs-number">1</span>] := TdxChartPaletteItem.Create(TdxAlphaColors.Green);
AChartPalette.Items[<span class="hljs-number">2</span>] := TdxChartPaletteItem.Create(TdxAlphaColors.Blue);
dxChartControl1.Palette := AChartPalette;
<span class="hljs-keyword">end</span>;</code></pre>
</div>
</div>
<p> You can also switch between color palettes at runtime, if necessary. </p><img src="/subscriptions/i/24.1/24-1-vcl-chart-palettes.png"
srcset="/subscriptions/i/24.1/24-1-vcl-chart-palettes.png 1x, /subscriptions/i/24.1/24-1-vcl-chart-palettes@2x.png 2x" alt="Palettes - VCL Chart Control, DevExpress" width="1049" height="717" style="border: none"
id="ctl00_ctl00_Content_Content_ctl8671">
<p> You can find more information on predefined and custom palettes in our
<a href="https://docs.devexpress.com/VCL/404989/ExpressCharts/appearance-customization/vcl-chart-palettes?v=24.1" target="_blank" rel="noopener">Online Documentation</a></p> <span class="H-Separator"></span>
<h3 data-anchor="vcl-survey" data-toc-title="Survey - VCL">
<a name="vcl-survey" class="anchor"></a>Survey - VCL
</h3>
<h4 anchor=""> Your Feedback Matters! </h4>
<div id="ctl00_ctl00_Content_Content_SurveyContainer" data-control="survey" class="InlineSurvey">
<div data-role="SurveyContent" data-markdown="false" data-partial="false" data-multiple-results="None" data-survey-id="004be529-5827-4a9d-9fa0-5144665568a6" data-auth-required="true"
data-user-data="{"IsLoggedIn":false,"IsEmployee":false,"CustomerId":null}" style="display: none;">
</div>
<div data-role="AuthRequired" style="display: block;"> Please <a href="https://www.devexpress.com/MyAccount/LogIn/?returnUrl=https%3a%2f%2fwww.devexpress.com%2fsubscriptions%2fwhats-new%2f">login</a> to complete the survey. </div>
<div data-role="Loading" style="display: none;">
<img src="../../Content/Editors/ajax-loader.gif" style="border-width:0px;">
</div>
<div data-role="Completed" style="display: none;">
<h3> Survey Completed </h3>
<p class="sys-max-width-md-80 sys-max-width-lg-60"> Thank you for taking the time to complete this survey. Your responses have now been posted. If you want to follow up with additional information, feel free to send us an email at
<a href="mailto:clientservices@devexpress.com">clientservices@devexpress.com</a> anytime. </p>
</div>
<div data-role="AlreadyPassed" style="display: none;">
<h3> You've Already Completed This Survey </h3>
<p class="sys-max-width-md-80 sys-max-width-lg-60"> Our records show that you have already completed this survey. If you want to follow up with additional information, send us an email at
<a href="mailto:clientservices@devexpress.com">clientservices@devexpress.com</a>. </p>
</div>
<div data-role="Expired" style="display: none;">
<h3> This survey has expired </h3>
<p>If you want to share your feedback or request new functionality, please submit a new support ticket via the <a href="https://supportcenter.devexpress.com/">DevExpress Support Center</a>. We’ll be happy to follow up.</p>
</div>
</div>
</div>
<div id="ctl00_ctl00_Content_Content_TOC" class="Loaded">
<div class="Header"> What's New in v24.1 </div>
<ul style="top: 33px;">
<li><a href="#general">General</a>
<ul>
<li><a href="#devexpress-accessibility">Accessibility Enhancements</a></li>
<li><a href="#devexpress-dateonly-timeonly-support">Support of New .NET DateOnly and TimeOnly Types Across UI Platforms</a></li>
<li><a href="#system-text-json-support">.NET and .NET Framework — Migration from Newtonsoft.Json to System.Text.Json</a></li>
<li><a href="#nuget">Regenerate Your NuGet API Key (Feed)</a></li>
<li><a href="#nuget-docs">DevExpress NuGet Server - Enhanced Documentation</a></li>
</ul>
</li>
<li><a href="#winforms">WinForms</a>
<ul>
<li><a href="#winforms-dateonly-support">DateOnly & TimeOnly Type Support</a></li>
<li><a href="#xtragrid">Data Grid</a></li>
<li><a href="#xtratreelist">TreeList</a></li>
<li><a href="#xtraaccordion">Accordion</a></li>
<li><a href="#xtraribbon">Ribbon & Bars</a></li>
<li><a href="#xtraeditors">Data Editors</a></li>
<li><a href="#xtradocumentmanager">Document Manager</a></li>
<li><a href="#xtradocking">Docking Library</a></li>
<li><a href="#winforms-html-css-support">HTML & CSS Support</a></li>
<li><a href="#xtrapdfviewer">PDF Viewer</a></li>
<li><a href="#xtrarichtextedit">Rich Text Editor</a></li>
<li><a href="#winforms-svg-scroll-cursor">SVG Scroll Cursor</a></li>
<li><a href="#xtraspreadsheet">Spreadsheet</a></li>
<li><a href="#winforms-accessibility">Accessibility and UI Automation</a></li>
<li><a href="#winforms-misc">Miscellaneous Enhancements</a></li>
<li><a href="#winforms-performance">Performance Improvements</a></li>
<li><a href="#winforms-survey">Survey - WinForms</a></li>
</ul>
</li>
<li><a href="#wpf">WPF</a>
<ul>
<li><a href="#wpf-accessibility">Accessibility and UI Automation</a></li>
<li><a href="#wpf-dateonly-support">DateOnly & TimeOnly Type Support</a></li>
<li><a href="#dxgrid">Data Grid</a></li>
<li><a href="#wpf-font-icon-images">Font Icon Images</a></li>
<li><a href="#dxribbon">Ribbon & Bars</a></li>
<li><a href="#dxpdfviewer">PDF Viewer</a></li>
<li><a href="#dxrichtextedit">Rich Text Editor</a></li>
<li><a href="#dxpropertygrid">Property Grid</a></li>
<li><a href="#dxspreadsheet">Spreadsheet</a></li>
<li><a href="#dxthemes">Lightweight Themes</a></li>
<li><a href="#wpf-survey">Survey - WPF</a></li>
</ul>
</li>
<li><a href="#devextreme">JavaScript & ASP.NET Core</a>
<ul>
<li><a href="#js-splitter">New Splitter Component</a></li>
<li><a href="#js-ui-ux-api">UI/UX and API Enhancements</a></li>
<li><a href="#js-bundle">JS Script Size</a></li>
<li><a href="#js-angular-18">Angular 18 Support</a></li>
<li><a href="#js-angular-httpmodule">New DxHttpModule for Angular</a></li>
<li><a href="#js-shadow-dom">Shadow DOM Support (CTP)</a></li>
<li><a href="#js-accessibility">Accessibility</a></li>
<li><a href="#aspnetcore-date-only-time-only">ASP.NET Core - DateOnly/TimeOnly Type Support</a></li>
<li><a href="#aspnetcore-data-validation">ASP.NET Core - Data Validation</a></li>
<li><a href="#aspnetcore-richtexteditor">ASP.NET Core - Rich Text Editor</a></li>
<li><a href="#devextreme-survey">Survey - JavaScript & ASP.NET Core</a></li>
</ul>
</li>
<li><a href="#blazor">Blazor</a>
<ul>
<li><a href="#blazor-treelist">New TreeList (CTP)</a></li>
<li><a href="#blazor-htmleditor">New HTML Editor</a></li>
<li><a href="#blazor-pdfviewer">New PDF Viewer (CTP)</a></li>
<li><a href="#blazor-map">New Map</a></li>
<li><a href="#blazor-polarchart">New Polar Chart</a></li>
<li><a href="#blazor-daterangepicker">New Date Range Picker</a></li>
<li><a href="#blazor-dropdownbox">New DropDown Box</a></li>
<li><a href="#blazor-fileinput">New File Input</a></li>
<li><a href="#blazor-drawer">New Drawer</a></li>
<li><a href="#blazor-toast">New Toast</a></li>
<li><a href="#blazor-progressbar">New Progress Bar</a></li>
<li><a href="#blazor-bargauge">New Bar Gauge</a></li>
<li><a href="#blazor-sparkline">New Sparkline</a></li>
<li><a href="#blazor-rendering-engine">New Rendering Engine</a></li>
<li><a href="#blazor-keyboard-support">Keyboard Support</a></li>
<li><a href="#blazor-project-templates">Project Templates</a></li>
<li><a href="#blazor-grid">Grid</a></li>
<li><a href="#blazor-charts">Charts</a></li>
<li><a href="#blazor-combobox-tagbox">New ComboBox and TagBox</a></li>
<li><a href="#blazor-listbox">List Box</a></li>
<li><a href="#blazor-datetime-editors">Date Edit & Time Edit</a></li>
<li><a href="#blazor-file-management">File Management</a></li>
<li><a href="#blazor-form-layout">Form Layout</a></li>
<li><a href="#blazor-richtexteditor">Rich Text Editor</a></li>
<li><a href="#blazor-scheduler">Scheduler</a></li>
<li><a href="#blazor-window-popup">Window and Popup</a></li>
<li><a href="#blazor-survey">Survey - Blazor</a></li>
</ul>
</li>
<li><a href="#reporting">Reporting</a>
<ul>
<li><a href="#reporting-web">Reporting for Web</a></li>
<li><a href="#reporting-blazor">Reporting for Blazor</a></li>
<li><a href="#reporting-common">All Platforms</a></li>
<li><a href="#reporting-cloud-deployment">Cloud Deployment</a></li>
<li><a href="#reporting-accessibility">Accessibility</a></li>
<li><a href="#reporting-datasources">Data Sources</a></li>
<li><a href="#reporting-survey">Survey - Reporting</a></li>
</ul>
</li>
<li><a href="#dashboard">BI Dashboard</a>
<ul>
<li><a href="#dashboard-cascading-parameters">Cascading Parameters</a></li>
<li><a href="#web-dashboard">Web Dashboard Enhancements</a></li>
<li><a href="#dashboard-data-sources">Data Sources</a></li>
</ul>
</li>
<li><a href="#officefileapi">Office File API</a>
<ul>
<li><a href="#ofa-accessibility">Accessibility Enhancements</a></li>
<li><a href="#ofa-unix-printing">Printing on Unix-based Systems</a></li>
<li><a href="#ofa-export-to-svg">Export Documents to SVG</a></li>
<li><a href="#ofa-spreadsheet-api">Spreadsheet Document API</a></li>
<li><a href="#ofa-pdf-api">PDF Document API</a></li>
<li><a href="#ofa-word-api">Word Processing Document API</a></li>
<li><a href="#officefileapi-survey">Survey - Office File API</a></li>
</ul>
</li>
<li><a href="#maui">.NET MAUI</a>
<ul>
<li><a href="#maui-treeview">New TreeView Control</a></li>
<li><a href="#maui-slideview">New Slide View Control</a></li>
<li><a href="#maui-expander">New Expander Control</a></li>
<li><a href="#maui-scrollview">New Scroll View Control</a></li>
<li><a href="#maui-slider">New Slider Controls</a></li>
<li><a href="#maui-scheduler">Scheduler</a></li>
<li><a href="#maui-pdfviewer">PDF Viewer</a></li>
<li><a href="#maui-filtering-ui">Filtering UI</a></li>
<li><a href="#maui-htmledit">HTML Editor</a></li>
<li><a href="#maui-button">Button</a></li>
<li><a href="#maui-orientation-settings">Orientation-Based Settings</a></li>
<li><a href="#maui-net">Target Plain .NET</a></li>
<li><a href="#maui-performance">Optimized Memory Consumption</a></li>
<li><a href="#maui-build-settings">Build Settings</a></li>
<li><a href="#maui-common-namespace">Common XAML Namespace</a></li>
<li><a href="#maui-crm-demo">DevExpress CRM Demo</a></li>
<li><a href="#maui-survey">Survey - .NET MAUI</a></li>
</ul>
</li>
<li><a href="#xaf">XAF - App Framework</a>
<ul>
<li><a href="#xaf-blazor-crud">Blazor – CRUD</a></li>
<li><a href="#xaf-blazor-usability">Blazor – Usability</a></li>
<li><a href="#xaf-blazor-extra-modules">Blazor – Extra Modules</a></li>
<li><a href="#xaf-entity-framework">Entity Framework</a></li>
<li><a href="#xaf-security">Security System</a></li>
<li><a href="#xaf-multi-tenancy">Multi-Tenancy</a></li>
<li><a href="#xaf-cross-platform">Cross-Platform Enhancements</a></li>
<li><a href="#xaf-survey">Survey - XAF & Web API Service</a></li>
</ul>
</li>
<li><a href="#coderush">CodeRush</a>
<ul>
<li><a href="#cr-voice-support">Voice Support</a></li>
<li><a href="#cr-navigation">Navigation</a></li>
</ul>
</li>
<li><a href="#vcl">VCL</a>
<ul>
<li><a href="#vcl-download">Download Your Copy Today</a></li>
<li><a href="#vcl-rad-stydio-12-1">RAD Studio 12.1 Support</a></li>
<li><a href="#vcl-highdpi-support">High DPI Support</a></li>
<li><a href="#vcl-data-aware-controls-and-menu">Data-Aware Controls and Menu</a></li>
<li><a href="#vcl-ribbon">Ribbon Control</a></li>
<li><a href="#vcl-chart">Chart Control</a></li>
<li><a href="#vcl-survey">Survey - VCL</a></li>
</ul>
</li>
</ul>
</div>
</div>
</div>
</section>
<section class="Dark">
<div class="content">
<h2 class="sys-h-align-center"> Ready to Evaluate v24.1? </h2> <p class="sys-h-align-center"> With numerous new products and dozens of high-impact features, v24.1 allows you to build your best, without limits<br
class="sys-visibility-hidden sys-visibility-hidden sys-visibility-md-shown"> or compromise. Download our fully-functional 30-day trial today and experience the DevExpress difference today. </p> <p class="sys-h-align-center">
<a href="https://go.devexpress.com/devexpressdownload_universaltrial.aspx" class="Button Orange" data-caption="Ready to evaluate v24.1?">Download Free 30-Day Trial</a></p>
</div>
</section>
<section class="Gray">
<div class="content">
<div class="News">
<div class="NewsItems">
<div class="Item">
<div class="ItemContent">
<img src="/products/i/news/release-history.png" srcset="/products/i/news/release-history.png 1x, /products/i/news/release-history@2x.png 2x" alt="DevExpress What's New History" width="330" height="190" style="border: none"
id="ctl00_ctl00_Content_Content_ctl8858">
<h2> Explore our Release History </h2>
<p> Learn more about new controls, features, and enhancements across supported platforms (.NET Framework, .NET Core, JavaScript, and VCL) introduced in our previous major updates. </p>
<a href="/subscriptions/new-2023-2.xml">What's New in v23.2</a><br><a href="/subscriptions/new-2023-1.xml">What's New in v23.1</a><br><a href="/subscriptions/new-2022-2.xml">What's New in v22.2</a><br><a href="/support/versions.xml#major">Version History</a>
</div>
</div>
<div class="Item">
<div class="ItemContent">
<img src="/products/i/news/choose-framework-for-cross-platform-app-dev.png" srcset="/products/i/news/choose-framework-for-cross-platform-app-dev.png 1x, /products/i/news/choose-framework-for-cross-platform-app-dev@2x.png 2x"
alt="Choosing the UI Framework for Desktop and Mobile Cross-Platform Apps" width="330" height="190" style="border: none" id="ctl00_ctl00_Content_Content_ctl8876">
<h2> Choosing the UI Framework for Desktop & Mobile Cross-Platform Apps </h2>
<p> Choosing the best possible UI framework for a given platform is crucial as it shapes the development process, user experience, and ultimately, the success of the project. </p>
<a href="https://community.devexpress.com/blogs/mobile/archive/2024/05/02/choosing-a-framework-and-app-architecture-for-desktop-and-mobile-cross-platform-apps.aspx" target="_blank" rel="noopener">Read the blog post</a><br><a href="https://community.devexpress.com/tags/v24.1/default.aspx" target="_blank" rel="noopener">Explore our blog posts about v24.1</a>
</div>
</div>
<div class="Item">
<div class="ItemContent">
<img src="/products/i/news/office-file-api-openai.png" srcset="/products/i/news/office-file-api-openai.png 1x, /products/i/news/office-file-api-openai@2x.png 2x" alt="Office File API — Enhance Accessibility using OpenAI Models"
width="330" height="190" style="border: none" id="ctl00_ctl00_Content_Content_ctl8888">
<h2> Office File API — Enhance Accessibility using OpenAI Models </h2>
<p> Learn how to integrate the OpenAI model into a DevExpress-powered Office File API application and add missing media descriptions and Alt Text. After processing documents, users can export files to accessible PDFs or upload them in
a document viewer and read with a screen reader. </p>
<a href="https://community.devexpress.com/blogs/office/archive/2024/05/08/enhance-accessibility-in-office-documents-word-and-excel-using-artificial-intelligence-system.aspx" target="_blank" rel="noopener">Read the blog post</a><br><a href="https://community.devexpress.com/tags/v24.1/default.aspx" target="_blank" rel="noopener">Explore our blog posts about v24.1</a>
</div>
</div>
</div>
</div>
</div>
</section>
</main>
<footer id="FooterTop">
<section>
<div class="r-container">
<a tabindex="-1" title="Footer" class="Footer-Toggle open" data-behavior="Footer-Toggle" href="javascript:;"><span></span></a>
<div class="Icons">
<a tabindex="-1" title="DevExpress Blogs" rel="noopener" aria-label="DevExpress Blogs" href="https://community.devexpress.com/blogs/" target="_blank"><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 36 36" style="enable-background:new 0 0 36 36;" xml:space="preserve" width="36px" height="36px"><title xmlns="">DevExpress Blogs</title>
<style type="text/css">
.orange_icon{fill:#FF7200;}
</style>
<path class="orange_icon" d="M14.8,19.6c-1.4,0-2.6,1.2-2.6,2.6s1.2,2.6,2.6,2.6s2.6-1.2,2.6-2.6S16.3,19.6,14.8,19.6z"></path>
<path class="orange_icon" d="M18,0C8.1,0,0,8.1,0,18c0,9.9,8.1,18,18,18s18-8.1,18-18C36,8.1,27.9,0,18,0z M14.8,28
C11.6,28,9,25.4,9,22.2V11.5c0-0.9,0.7-1.6,1.6-1.6c0.9,0,1.6,0.7,1.6,1.6V17c0.8-0.4,1.7-0.6,2.6-0.6c3.2,0,5.8,2.6,5.8,5.8
C20.6,25.4,18,28,14.8,28z M22.6,22.2c0-4.3-3.5-7.8-7.8-7.8v-3.2c6.1,0,11,4.9,11,11H22.6z M27.8,22.2C27.8,15,22,9.2,14.8,9.2V6
C23.8,6,31,13.2,31,22.2H27.8z"></path>
</svg></a>
<div class="separator">
</div><a tabindex="-1" title="Facebook" rel="noopener" aria-label="Facebook" href="https://www.facebook.com/DevExpress" target="_blank"><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 36 36" style="enable-background:new 0 0 36 36;" xml:space="preserve" width="36px" height="36px"><title xmlns="">Facebook</title>
<style type="text/css">
.facebook_icon{fill:#3D5A98;}
</style>
<path class="facebook_icon" d="M18,0C8.1,0,0,8.1,0,18c0,9.9,8,18,18,18V24.3h-4.3v-5H18v-3.7c0-4.3,2.7-6.6,6.5-6.6
c1.8,0,3.4,0.1,3.9,0.2v4.5l-2.7,0c-2.1,0-2.5,1-2.5,2.4v3.2h4.9l-0.6,5h-4.3v10.9C30.6,33,36,26.1,36,18C36,8.1,27.9,0,18,0z"></path>
</svg></a><a tabindex="-1" title="Twitter" rel="noopener" aria-label="Twitter" href="https://twitter.com/DevExpress" target="_blank"><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 36 36" style="enable-background:new 0 0 36 36;" xml:space="preserve" width="36px" height="36px"><title xmlns="">Twitter</title>
<path d="M13,9c4.2,6,8.4,12.1,12.7,18.1c-0.1,0-2.4,0-2.7,0C18.7,21.1,14.5,15,10.3,9C11.2,9,12.1,9,13,9z M36,18
c0,9.9-8.1,18-18,18S0,27.9,0,18C0,8.1,8.1,0,18,0S36,8.1,36,18z M28.2,28.4c-2.8-4-5.5-8-8.2-12c2.5-2.9,5-5.9,7.6-8.8
c-0.6,0-1.2,0-1.8,0c-0.7,0.8-1.5,1.7-2.2,2.5c-0.7,0.8-1.5,1.7-2.2,2.5c-0.7,0.8-1.5,1.7-2.2,2.5c-1.8-2.6-3.5-5.1-5.2-7.6
c-2,0-4,0-6,0c0,0,0,0,0,0c0,0,0,0,0,0c2.6,3.8,5.3,7.7,7.9,11.5c-0.4,0.5-0.9,1-1.3,1.5c-0.4,0.5-0.9,1-1.3,1.5
c-0.4,0.5-0.9,1-1.3,1.5c-0.4,0.5-0.9,1-1.3,1.5c-0.4,0.5-0.9,1-1.3,1.5c-0.5,0.6-1.3,1.5-1.3,1.5c0.6,0,1.2,0,1.8,0
c2.3-2.7,4.6-5.4,6.9-8.1c1.9,2.7,3.7,5.4,5.5,8.1C24.1,28.4,26.1,28.4,28.2,28.4z"></path>
</svg></a><a tabindex="-1" title="YouTube" rel="noopener" aria-label="YouTube" href="https://www.youtube.com/user/DeveloperExpress" target="_blank"><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 36 36" style="enable-background:new 0 0 36 36;" xml:space="preserve" width="36px" height="36px"><title xmlns="">YouTube</title>
<style type="text/css">
.youtube_0{fill-rule:evenodd;clip-rule:evenodd;fill:#E2E2E2;}
.youtube_1{fill-rule:evenodd;clip-rule:evenodd;fill:#444444;}
.youtube_2{fill-rule:evenodd;clip-rule:evenodd;fill:#D62929;}
.youtube_3{fill-rule:evenodd;clip-rule:evenodd;fill:#FFFFFF;}
</style>
<circle class="youtube_0" cx="18" cy="18" r="18"></circle>
<path class="youtube_1" d="M15.9,6h-1.4l-0.9,3.5l-1-3.5h-1.4c0.3,0.8,0.6,1.7,0.9,2.5c0.4,1.3,0.7,2.2,0.8,2.8V15h1.4v-3.6L15.9,6z
M19.5,12.8v-2.3c0-0.7-0.1-1.2-0.4-1.6c-0.3-0.5-0.8-0.7-1.4-0.7c-0.6,0-1.1,0.2-1.4,0.7c-0.3,0.3-0.4,0.9-0.4,1.6v2.3
c0,0.7,0.1,1.2,0.4,1.6c0.3,0.5,0.8,0.7,1.4,0.7c0.6,0,1.1-0.2,1.4-0.7C19.4,14,19.5,13.5,19.5,12.8z M18.3,13
c0,0.6-0.2,0.9-0.6,0.9c-0.4,0-0.6-0.3-0.6-0.9v-2.8c0-0.6,0.2-0.9,0.6-0.9c0.4,0,0.6,0.3,0.6,0.9V13z M24,15V8.3h-1.2v5.1
C22.6,13.8,22.3,14,22,14c-0.2,0-0.3-0.1-0.3-0.3c0,0,0-0.2,0-0.5V8.3h-1.2v5.3c0,0.5,0,0.8,0.1,1c0.1,0.3,0.4,0.5,0.8,0.5
c0.4,0,0.9-0.3,1.4-0.8V15H24z"></path>
<path class="youtube_2" d="M28,23.1c0,1.5,0,3.2-0.4,4.7c-0.2,1.1-1.1,1.8-2.2,1.9C23,30,20.5,30,18,30c-2.5,0-5,0-7.5-0.3
c-1-0.1-1.9-0.9-2.2-1.9C8,26.3,8,24.6,8,23.1l0,0c0-1.5,0-3.2,0.4-4.7c0.2-1.1,1.1-1.8,2.2-1.9c2.5-0.3,5-0.3,7.5-0.3
c2.5,0,5,0,7.5,0.3c1,0.1,1.9,0.9,2.2,1.9C28,19.9,28,21.5,28,23.1L28,23.1z"></path>
<path class="youtube_3" d="M13.7,19.7v-1.3H9.5v1.3h1.4v7.6h1.3v-7.6H13.7z M16.1,27.4v-0.7c-0.5,0.5-0.9,0.8-1.4,0.8
c-0.4,0-0.7-0.2-0.8-0.5c-0.1-0.2-0.1-0.5-0.1-1v-5.2h1.2v4.9c0,0.3,0,0.4,0,0.5c0,0.2,0.1,0.3,0.3,0.3c0.2,0,0.5-0.2,0.8-0.6v-5.1
h1.2v6.6H16.1z M20.7,25.5c0,0.6-0.2,0.9-0.5,0.9c-0.2,0-0.4-0.1-0.6-0.3v-4c0.2-0.2,0.4-0.3,0.6-0.3c0.3,0,0.5,0.3,0.5,0.9V25.5z
M21.9,25.4v-2.6c0-0.6,0-1.1-0.1-1.3c-0.2-0.5-0.5-0.7-1-0.7c-0.4,0-0.9,0.2-1.2,0.7v-2.9h-1.2v8.9h1.2v-0.6
c0.4,0.5,0.8,0.7,1.2,0.7c0.5,0,0.8-0.3,1-0.7C21.9,26.4,21.9,26,21.9,25.4z M25.3,23.3h-1.2v-0.6c0-0.6,0.2-0.9,0.6-0.9
c0.4,0,0.6,0.3,0.6,0.9V23.3z M26.5,25.3v-0.2h-1.2c0,0.5,0,0.7,0,0.8c-0.1,0.3-0.2,0.5-0.5,0.5c-0.4,0-0.6-0.3-0.6-0.9v-1.2h2.4
v-1.4c0-0.7-0.1-1.2-0.4-1.6c-0.3-0.5-0.8-0.7-1.4-0.7c-0.6,0-1.1,0.2-1.4,0.7c-0.3,0.3-0.4,0.9-0.4,1.6v2.3c0,0.7,0.1,1.2,0.4,1.6
c0.3,0.5,0.8,0.7,1.5,0.7c0.6,0,1.1-0.2,1.5-0.7c0.1-0.2,0.2-0.5,0.3-0.7C26.5,25.9,26.5,25.6,26.5,25.3z"></path>
</svg></a>
</div>
<div class="h-clear">
</div>
</div>
</section>
</footer>
<footer id="FooterExpanding">
<section data-role="FooterExpandableContent" data-state="expanded" style="display:block;height:auto;">
<div class="FooterMain">
<div class="r-container">
<div class="Separator">
</div>
<div class="grid">
<div class="col col1">
<div class="Group"> About Us </div>
<a tabindex="-1" href="https://www.devexpress.com/aboutus/">About DevExpress</a><a tabindex="-1" href="https://www.devexpress.com/aboutus/newsreviews/">News</a><a tabindex="-1" href="https://www.devexpress.com/aboutus/awards/">Our Awards</a><a tabindex="-1" href="https://www.devexpress.com/aboutus/events/">Events, Meetups and Tradeshows</a><a tabindex="-1" href="https://www.devexpress.com/aboutus/testimonials/">User Comments and Case Studies</a><a tabindex="-1" href="https://www.devexpress.com/aboutus/mvp/">MVP Program</a><a tabindex="-1" href="https://www.devexpress.com/aboutus/#logos">Logos and Artwork</a>
<div class="Group"> Frequently Asked Questions </div>
<a tabindex="-1" href="https://www.devexpress.com/support/eulas/">Product Licensing</a><a tabindex="-1" href="https://www.devexpress.com/support/order/">Purchasing FAQ</a><a tabindex="-1" href="https://www.devexpress.com/support/versions.xml">Supported Versions & IDE Prerequisites</a><a tabindex="-1" href="https://docs.devexpress.com/GeneralInformation/2219/support-services">Support Policies</a><a tabindex="-1" href="https://www.devexpress.com/support/eulas/hotfix-policy.xml">Maintenance Release FAQ</a>
</div>
<div class="col col2">
<div class="Group"> Windows Desktop Controls </div>
<a tabindex="-1" href="https://www.devexpress.com/products/net/controls/winforms/">WinForms</a><a tabindex="-1" href="https://www.devexpress.com/products/net/controls/wpf/">WPF</a><a tabindex="-1" href="https://www.devexpress.com/products/vcl/">VCL</a><a tabindex="-1" href="https://www.devexpress.com/subscriptions/reporting/">Desktop Reporting</a>
<div class="Group"> Enterprise & Server Tools </div>
<a tabindex="-1" href="https://www.devexpress.com/products/net/dashboard/">Business Intelligence Dashboard</a><a tabindex="-1" href="https://www.devexpress.com/products/net/report-server/">Report & Dashboard Server</a><a tabindex="-1" href="https://www.devexpress.com/products/net/office-file-api/">Office File API</a>
<div class="Group"> Mobile Controls </div><a tabindex="-1" href="https://www.devexpress.com/maui/">.NET MAUI (FREE)</a><a tabindex="-1" href="https://www.devexpress.com/xamarin/">Xamarin UI Controls (FREE)</a>
</div>
<div class="h-clear hidden-sm">
</div>
<div class="col col3">
<div class="Group"> Web Controls </div>
<a tabindex="-1" href="https://js.devexpress.com">JS - jQuery, Angular, React</a><a tabindex="-1" href="https://www.devexpress.com/blazor/">Blazor</a><a tabindex="-1" href="https://www.devexpress.com/products/net/controls/asp/">ASP.NET Web Forms</a><a tabindex="-1" href="https://www.devexpress.com/products/net/controls/asp/mvc/">ASP.NET MVC and Core</a><a tabindex="-1" href="https://www.devexpress.com/products/net/controls/asp/bootstrap-webforms.xml">Bootstrap Web Forms</a><a tabindex="-1" href="https://www.devexpress.com/subscriptions/reporting/">Web Reporting</a>
<div class="Group"> Frameworks & Productivity </div>
<a tabindex="-1" href="https://www.devexpress.com/products/net/application_framework/">XAF - Cross-Platform .NET App UI</a><a tabindex="-1" href="https://www.devexpress.com/products/net/orm/">XPO - ORM Library (FREE)</a><a tabindex="-1" href="https://www.devexpress.com/products/coderush/">CodeRush for Visual Studio (FREE)</a><a tabindex="-1" href="https://www.devexpress.com/products/net/application_framework/security-web-api-service.xml">.NET App Security & Web API Service (FREE)</a>
<div class="Group"> Testing & QA </div><a tabindex="-1" href="https://www.devexpress.com/products/testcafestudio">TestCafe Studio - Web Testing</a>
</div>
<div class="col col4">
<div class="Group"> Support & Documentation </div>
<a tabindex="-1" href="https://supportcenter.devexpress.com/ticket/list">Search the KB</a><a tabindex="-1" href="https://supportcenter.devexpress.com/ticket/list?preset=mytickets">My Questions</a><a tabindex="-1" href="https://docs.devexpress.com/">Documentation</a><a tabindex="-1" href="https://supportcenter.devexpress.com/ticket/list?preset=examples">Code Examples</a><a tabindex="-1" href="https://www.devexpress.com/support/demos/">Demos & Getting Started</a><a tabindex="-1" href="https://community.devexpress.com/blogs/">Blogs</a><a tabindex="-1" href="https://www.devexpress.com/trainingcenter/">Training</a><a tabindex="-1" href="https://www.devexpress.com/subscriptions/whats-new/">What's New</a>
</div>
<div class="h-clear hidden-sm">
</div>
<div class="h-clear">
</div>
</div>
</div>
</div>
<div class="FooterExtra">
<div class="r-container">
<p>DevExpress engineers feature-complete Presentation Controls, IDE Productivity Tools, Business Application Frameworks, and Reporting Systems for Visual Studio, Delphi, HTML5 or iOS & Android development. Whether using WPF, ASP.NET,
WinForms, HTML5 or Windows 10, DevExpress tools help you build and deliver your best in the shortest time possible.</p>
<p> We are here to help. Should you have any questions or need assistance from a member of our team, write to us at <a href="mailto:info@devexpress.com" tabindex="-1">info@devexpress.com</a>. </p>
</div>
</div>
</section>
</footer>
<footer id="FooterBottom">
<section>
<div class="r-container">
<div class="Privacy"> Use of this site constitutes acceptance of our <a href="https://www.devexpress.com/aboutus/legal.xml" tabindex="-1">Website Terms of Use</a> and
<a href="https://www.devexpress.com/aboutus/privacy-policy.xml" tabindex="-1">Privacy Policy (Updated)</a>. <!-- OneTrust Cookies Settings button start -->
<span id="ot-sdk-btn" class="ot-sdk-show-settings">Cookies Settings</span>
<!-- OneTrust Cookies Settings button end -->
</div>
<div class="Copyright"> Copyright © 1998-2024 Developer Express Inc. All trademarks or registered trademarks are property of their respective owners </div>
</div>
</section>
</footer>
<script src="https://www.devexpress.com/Scripts/SharedInit?v=t17k5cBhcUWcfNazL0Lllk8N0Jp2k2K5IcJnR1uV_ow1"></script>
<script src="https://www.devexpress.com/Scripts/WebFormsInit?v=PBM0RCFNvblcuHX3jiaSCKDewGs4_QGdf2z7Z2d5qnM1"></script>
<script src="https://www.devexpress.com/Scripts/SiteNotifications/SiteNotificationsScriptsBundle?v=LzwkIF4IshfXXKblVkqESLgQHcXlMw7jBmiDsd9HbU81"></script>
<script src="https://www.devexpress.com/$Tesseract/ScriptsInitialize/Bundle?v=bNbA7JgouazvcfRL-yPIAwr74CKUvZUr7m0RGKEbr6o1"></script>
<div id="GlobalBackToTopButton" class="BackToTopButton Hidden">
<div class="Button">
</div>
</div>
<div id="InPageChat" class="InPageChat Hidden">
<div title="Live Chat" class="ChatButton">
</div>
</div>
<script type="text/javascript">
//<![CDATA[
window.AutoTOC_ctl00_ctl00_Content_Content_TOC = new AutoTOC.Controller('ctl00_ctl00_Content_Content_Content', 'ctl00_ctl00_Content_Content_TOC');
Prism.plugins.autoloader.languages_path = "/Scripts/Prism/components/";
Prism.plugins.NormalizeWhitespace.setDefaults({
'remove-trailing': true,
'remove-indent': true,
'left-trim': true,
'right-trim': false,
});
//]]>
</script>
</form>
Text Content
Chat Now CartMy DownloadsFree TrialLog In * Products Products MULTI-PLATFORM PACKAGES Universal SubscriptionOur Best Value – includes over 600 UI Controls, our award-winning reporting platform, DevExpress Dashboard, the eXpressApp Framework, CodeRush for Visual Studio and more.DXperience SubscriptionSave Hundreds – includes DevExpress UI Controls for WinForms, ASP.NET, MVC, WPF, our award-winning reporting platform and CodeRush for Visual Studio. WINDOWS DESKTOP CONTROLS WinFormsWPFVCLDesktop Reporting ENTERPRISE & SERVER TOOLS Business Intelligence DashboardReport & Dashboard ServerOffice File API (XLS, DOC, PDF) MOBILE CONTROLS .NET MAUI (FREE)Xamarin UI Controls (FREE) WEB CONTROLS JavaScript – jQuery, Angular, React, VueBlazorASP.NET Web FormsASP.NET MVCASP.NET CoreBootstrap Web FormsWeb Reporting FRAMEWORKS & PRODUCTIVITY XAF - Cross-Platform .NET App UIXPO – ORM Library (FREE).NET App Security & Web API Service (FREE)CodeRush for Visual Studio (FREE) TESTING & QA TestCafe Studio What's New.NET 8 Support * * Demos * * Buy * * Support & Docs Support & Docs SUPPORT CENTER Search the KB My Questions Localization Version History What's New in the Latest Version LEARNING MATERIALS Documentation Code Examples Demos Training NEED HELP OR REQUIRE MORE INFORMATION? Submit your support inquiries via the DevExpress Support Center for assistance. * * Blogs * * About Us About Us CONNECT WITH DEVEXPRESS Blogs Events, Meetups and Tradeshows LEARN MORE ABOUT DEVEXPRESS About Us News User Comments and Case Studies Our Awards MVP Program ANNOUNCING DEVEXPRESS UNIVERSAL V24.1 Developer Express Inc is proud to announce the immediate availability of its newest release, DevExpress v24.1. Built and optimized for desktop, web, and mobile developers alike... DEVEXPRESS WINS 19 VISUAL STUDIO READER'S CHOICE AWARDS Like previous years, DevExpress dominated Visual Studio Magazine's 2023 Readers Choice Awards. We thank all our loyal users for casting their vote on behalf of DevExpress. WHEN ONLY THE BEST WILL DO V24.1 IS NOW AVAILABLE Your skills, our tools. Let's build great apps together. Free 30-Day TrialDownload v24.1 EXPLORE OUR NEWEST FEATURES (V24.1) General Accessibility DateOnly/TimeOnly Support System.Text.Json Support NuGet Windows Desktop Controls WinForms WPF VCL Web Controls JavaScript & ASP.NET Core Blazor Enterprise & Server Tools Reporting Business Intelligence Dashboard Office File API Mobile Components .NET MAUI (FREE) Frameworks & Productivity XAF - Cross-Platform .NET App UI .NET App Security & Web API (FREE) CodeRush (FREE) CROSS-PLATFORM ENHANCEMENTS V24.1 ACCESSIBILITY ENHANCEMENTS Accessibility support remains a top engineering priority. Accordingly, we enhanced keyboard navigation/screen reader support, extended automation capabilities and other accessibility-related features to ensure better compliance with standards outlined in WCAG. This release includes enhancements across most of our desktop and web component suites: * WinForms Controls * WPF Controls * DevExtreme JavaScript Components * Blazor UI Components * ASP.NET Core Controls * .NET Reporting * XAF - Cross-Platform .NET App UI (Blazor) * VCL Controls SUPPORT OF NEW .NET DATEONLY AND TIMEONLY TYPES ACROSS UI PLATFORMS We now support DateOnly and TimeOnly types in data-aware UI controls (such as Data Grid, Tree List, Date and Time Editors) for the following UI platforms in .NET Core / .NET 6+ apps. * WinForms Controls * WPF Controls * Blazor UI Components * XAF - Cross-Platform .NET App UI (Blazor) * Please review the links above for additional information (supported features vary across UI platforms and controls). Thanks to changes at core levels (our DevExpress.Data and DevExtreme.AspNet.Data libraries), we now support these data types for our client/in-memory and server mode data sources (both of which are used by multiple UI controls listed above): * EntityServerModeSource / EntityInstantFeedbackSource * LinqServerModeSource / LinqInstantFeedbackSource * GridDevExtremeDataSource (for ASP.NET Core / DevExtreme and Blazor-based controls) You can sort, group, and filter data (and other capabilities) against DateOnly and TimeOnly values. We also extended our criteria language as follows: * You can use date/time-related functions (such as AddHours, GetDays, DateDiffDays, etc.) in filter expressions and unbound columns. * You can now wrap DateOnly/TimeOnly constants in '#' and '!' for string filter expressions: [OrderDate] >= #!2018-03-22!# && [OrderTime] >= #!18:22:00!# Due to the following Microsoft-related breaking change these new data types are of special importance to EF Core 8 developers: SQL Server date and time now scaffold to .NET DateOnly and TimeOnly. DevExpress customers will benefit from this new functionality even if NOT using EF Core 8 for data access – it is just important that the underlying database or IQueryable provider supports the new data types (like Microsoft SQL Server with EF Core 8). Here is a quote from Microsoft about the general value for .NET developers: DateOnly and TimeOnly were introduced in .NET 6.0, and are a perfect match for mapping the database date and time types. DateTime notably contains a time component that goes unused and can cause confusion when mapping it to date, and TimeSpan represents a time interval - possibly including days - rather than a time of day at which an event occurs. Using the new types prevents bugs and confusion, and provides clarity of intent. Note: Microsoft and third-party package vendors did not backport DateOnly and TimeOnly types on .NET Framework. Additionally, we do not officially support this feature for .NET Framework and OData/XPO data sources within both frameworks. We encourage you to migrate to .NET 6+ to benefit from the new data types. Technically, we share parts of our codebase between .NET Framework and .NET, so do not be confused that our DevExpress.Data library for .NET Framework includes our own "shim" DateOnly and TimeOnly types. If you experience any conflicts with third-party compatibility packages (like one or two for unofficial support), we recommend that you remove these packages. .NET AND .NET FRAMEWORK — MIGRATION FROM NEWTONSOFT.JSON TO SYSTEM.TEXT.JSON In our v24.1 release cycle, the following DevExpress products will use Microsoft’s System.Text.Json instead of Newtonsoft.Json for JSON serialization-related tasks in runtime code: * Data Access Library: BI Dashboards (DashboardJsonDataSource) and Reporting (JsonDataSource) for .NET 6+ WinForms, WPF, Blazor, ASP.NET Core apps (.NET Framework apps will continue to use the Newtonsoft.Json library. We expect to switch to System.Text.Json in our v24.2 release cycle). Breaking Change * Data Access Library for .NET 6+ and .NET Framework DevExtreme, Blazor and ASP.NET Core apps (a System.Text.Json-compatible version of DevExtreme.AspNet.Data v4.0.0+ is now available). Breaking Change * Backend Web API Service for .NET 6+ non-XAF apps (DevExtreme, Blazor, .NET MAUI, etc.) and XAF apps. Breaking Change * Maps in .NET 6+ WinForms in WPF, Blazor, ASP.NET Core apps (.NET Framework apps will continue to use the Newtonsoft.Json library. We expect to switch to System.Text.Json in our v24.2 release cycle). Breaking Change * Blazor Rich Text Editor (no Breaking Changes). Our design-time code (wizards, designers and tools) may still continue to use Newtonsoft.Json, because of dependencies within Visual Studio (some design-time services still rely on Newtonsoft.Json, but we believe this will change in the future). Remaining .NET Framework products that currently rely on the Newtonsoft.Json library, will likely switch to System.Text.Json in the future. Here we rely on the minimally supported .NET Framework version for DevExpress products, which will likely change from 4.5.2 to 4.6.2 in v24.2. REGENERATE YOUR NUGET API KEY (FEED) To regenerate the NuGet API key, navigate to https://nuget.devexpress.com/ and click the Regenerate Feed link. Your NuGet API key is sensitive information, and you should protect it from unauthorized use by untrusted third parties. If you have leaked your NuGet API key, you need to regenerate it as soon as possible. Cases or reasons to regenerate a NuGet API key may include, but are not limited to, the following: * You included your NuGet API key in a public forum post, GitHub repository, log files, or other authorized place by mistake. * Members of your team who previously had access to your NuGet Feed have left the company. * You know or suspect that your NuGet API key has been stolen or compromised. DEVEXPRESS NUGET SERVER - ENHANCED DOCUMENTATION We updated our online documentation to address popular usage scenarios based on user feedback. We clarified which DevExpress NuGet feed (offline or online) to use for Windows, Mac OS, Linux: * Choose Between Offline and Online DevExpress NuGet Feeds * Install NuGet Packages in Visual Studio, VS Code, and Rider * Integration with GitLab * Security Best Practices for other CI/CD Systems WINFORMS CONTROLS V24.1 DateOnly & TimeOnly Type Support Data Grid TreeList Accordion Ribbon & Bars Data Editors Document Manager Docking Library HTML & CSS Support PDF Viewer Rich Text Editor SVG Scroll Cursor Spreadsheet Accessibility and UI Automation Miscellaneous Enhancements Performance Improvements Survey - WinForms Your feedback matters. Please, review the description of WinForms-related features below and leave your feedback at the end of the section. Go to the survey now. DATEONLY & TIMEONLY TYPE SUPPORT DevExpress WinForms data-aware UI controls (such as our Data Grid and TreeList) and the Date Editor now support DateOnly and TimeOnly data types (in .NET applications). These data types offer the following advantages (versus the traditional DateTime type): usage clarity, improved database compatibility, less space during serialization, and the ability to mitigate potential errors/inconsistencies related to different time zones. Built-in DateOnly/TimeOnly support extends to: * UI Elements Related to Data Filtering (Column Filter Popup, Filter Editor, Expression Editor, Automatic Filter Row) * Conditional Formatting Rules * Data Summaries * Data Grouping * Unbound Columns * Masks * Search * Criteria Operators * C# gridView.ActiveFilterString = "[Date]=#!2022-02-01!#"; We also added DateOnly/TimeOnly type support within our server-based data sources: * EntityServerModeSource / EntityInstantFeedbackSource * LinqServerModeSource / LinqInstantFeedbackSource You can sort, group, and filter data in server mode sources against DateOnly and TimeOnly values. And yes, you can use date/time-related functions (such as AddHours(), GetDays(), DateDiffDays()) in filter expressions and unbound columns. DATA GRID #MERGED CELL EDITING As its name implies, users can now simultaneously edit all cells in a merged range or modify separate cells (in GridView and BandedGridView) as needs dictate. Use the new MergedCellEditMode property to activate this feature and specify how users edit merged cell data. Options include: * VisibleCells – Edits data cells in a merged range. * FocusedCell – Edits data cells in a merged range for the focused row. * Disabled * C# using DevExpress.XtraGrid.Views.Grid; // Allows users to edit data cells in a merged range. gridView1.OptionsView.MergedCellEditMode = MergedCellEditMode.VisibleCells; Run Demo To execute this demo, you must first install the DevExpress WinForms product library . #DISPLAY CUSTOM UI ELEMENTS IN THE FIND PANEL v24.1 includes new APIs to display predefined and/or custom UI controls in the Find Panel. With this new option, you can build fully customizable/personalized interfaces when using the DevExpress Find Panel. Use view.FilterPanelItems to introduce custom Find Panel UI elements in your WinForms app: * AddControl — Displays the specified UI control. * AddButton — Displays a button. * AddCheckButton — Displays a checked button. * AutoHeight — Updates Find Panel height to match UI elements. * RemoveItem / RemoveItems – Removes the specified UI element(s) from the Find Panel. * C# // This code snippet comes from the Find Panel module in our WinForms Data Grid demo (v24.1). CheckButton showCustomButton = null; void ceShowCustomButton_CheckedChanged(object sender, EventArgs e) { CheckEdit customButton = sender as CheckEdit; if(customButton.Checked) { showCustomButton = view.FindPanelItems.AddCheckButton(customButtonName, null, view.OptionsFind.Behavior != FindPanelBehavior.Search, (button, args) => { CheckButton checkButton = button as CheckButton; view.OptionsFind.Behavior = checkButton.Checked ? FindPanelBehavior.Filter : FindPanelBehavior.Search; checkButton.ToolTip = "Find Panel Mode"; icbFindPanelBehavior.EditValue = view.OptionsFind.Behavior; }); showCustomButton.ImageOptions.ImageUri.Uri = "Filter;Size16x16;Svg"; } else { showCustomButton = null; view.FindPanelItems.RemoveItem(customButtonName); } icbFindPanelBehavior.Enabled = showCustomButton == null; } Run Demo To execute this demo, you must first install the DevExpress WinForms product library . #HIDE SPECIFIC FILTERS FROM EXCEL-INSPIRED FILTER DROPDOWN The WinForms Data Grid control exposes a ShowFilterPopupExcel event and allows you to hide specific filter options from "Filters" and "Values" tabs of our Excel-style Filter Dropdown. v24.1 adds a e.HideFilter(filterType) method to event arguments for advanced customization of the filter menu. Use this method to hide unnecessary filter operators from the "Filters" tab. We also introduced this feature in our WinForms TreeList control. * C# void gridView1_ShowFilterPopupExcel(object sender, DevExpress.XtraGrid.Views.Grid.FilterPopupExcelEventArgs e) { if (e.Column.FieldName == "UnitPrice") { e.HideFilter(DevExpress.Utils.Filtering.Internal.CustomUIFilterType.BelowAverage); e.HideFilter(DevExpress.Utils.Filtering.Internal.CustomUIFilterType.Between); e.HideFilter(DevExpress.Utils.Filtering.Internal.CustomUIFilterType.BottomN); // ... } } #DISPLAY A CUSTOM DEVEXPRESS POPUP MENU We've made it easier to display the DevExpress PopupMenu for individual Data Grid UI elements. In previous versions, you had to customize the built-in menu (add/remove menu items) within the control's PopupMenuShowing event. With v24.1, you can display a custom menu (created and customized at design time or runtime) using the new e.ShowCustomMenu method: * C# void gridView1_PopupMenuShowing(object sender, PopupMenuShowingEventArgs e) { if (e.MenuType == GridMenuType.Column) { popupMenu_Column.Tag = e.HitInfo; popupMenu_Column.MenuCaption = $"{e.HitInfo.Column}"; e.ShowCustomMenu(popupMenu_Column); } } API enhancements extend to: DevExpress TreeList, Vertical Grid (Property Grid), and Pivot Grid. How to: Implement a Custom Menu in the DevExpress WinForms Data Grid #EXPORT CELL IMAGES TO EXCEL The WinForms Data Grid control now exports images (raster and SVG) displayed within cells of bound and unbound columns to XLSX in data-aware export mode. Cell images are exported as a Byte[] array. To activate this feature, set the AllowCellImages property to DefaultBoolean.True. * C# void btnExport_Click(object sender, EventArgs e) { DevExpress.XtraPrinting.XlsxExportOptionsEx options = new DevExpress.XtraPrinting.XlsxExportOptionsEx(); options.AllowCellImages = DevExpress.Utils.DefaultBoolean.True; advBandedGridView1.ExportToXlsx("grid_export.xlsx", options); } Run Demo To execute this demo, you must first install the DevExpress WinForms product library . You can customize cell images or replace values with images (based on export conditions) before the Grid Control generates the output document. Handle the CustomizeCell event as follows: * C# void Options_CustomizeCell(DevExpress.Export.CustomizeCellEventArgs e) { if(e.ColumnFieldName == "Photo" && e.Value == null) { e.Value = XtraEditors.Controls.ByteImageConverter.ToByteArray(imageCollection1.Images["car"]); e.Handled = true; } } #CALCULATE THE BEST SIZE Designed to address common layout-related dev tasks, the new CalcBestSize(maxSize, checkScrollInfo) method calculates the maximum allowable size of the Grid Control (to display as many data rows and columns as possible). #CUSTOM TILE PAINTING FOR THE DEVEXPRESS TILEVIEW (KANBAN) You can now customize tile appearance by handling the new TileView.CustomDrawTile event. With its comprehensive event arguments (APIs), you can easily change border shape and color or draw custom UI elements to address specific design requirements/user preferences. Run Demo To execute this demo, you must first install the DevExpress WinForms product library . And yes, you can render HTML and CSS templates inside tiles as needs dictate: Run Demo To execute this demo, you must first install the DevExpress WinForms product library . #DISPLAY TOOLTIPS FOR TRIMMED CONDITIONAL FORMATTING RULES If formatting rule name is larger than the width of the cell, the rule will appear in a tooltip when you hover over the cell: Run Demo To execute this demo, you must first install the DevExpress WinForms product library . #ANNOTATE CONDITIONAL FORMATTING RULES With this option, you and your end-users can include descriptive text for conditional formatting rules, offering insights into the purpose and logic behind each rule. Implementing text descriptions for conditional formatting rules is simple and intuitive. Users can add explanations directly in the Formatting Rule Editor, ensuring that context is available each time they view or change rules. To enable this feature, set the OptionsView.AllowFormatRuleDescription property to true. Note: we also introduced this feature in our WinForms TreeList, VerticalGrid, and PivotGrid controls. TREELIST #EXPAND NODES ON SEARCH With this new feature, users can effortlessly locate specific TreeList nodes, even if they are collapsed within a complex hierarchy. When users initiate a search within the DevExpress TreeList, the TreeList automatically expands relevant nodes to display search results (in previous versions, you could only search through expanded nodes). Use the TreeList's OptionsFind.ExpandNodesOnSearch setting to enable/disable the "Expand Nodes on Search" feature. Run Demo To execute this demo, you must first install the DevExpress WinForms product library . #IMPROVED PERFORMANCE FOR LARGE DATA SOURCES We improved WinFroms TreeList performance to better address usage scenarios when large data updates are made to the underlying data source. The following internal test results illustrate performance improvements: #AUTO-FILTER ROW FOCUS RETENTION This addition to our WinForms TreeList control ensures that user focus remains unaffected when using the Auto-Filter Row, even during data updates. In previous versions, the TreeList automatically closed the active editor in the Auto-Filter Row when updating data. In v24.1, the editor remains active (users can edit filter criteria during data updates). ACCORDION #DISPLAY ITEM CAPTIONS IN A MINIMIZED STATE We added a new CaptionShowMode property to control how the item caption is displayed when the Accordion control is minimized/collapsed. Options include: * Below Image * Above Image * None The new CaptionImageIndent property specifies the indent between the image and caption. #CONFIGURABLE ITEM INDENTS With this new option, you can introduce fully personalized side navigation logic. We added the ChildIndentStartLevel property. This property specifies the hierarchy level that starts the indentation of child elements. We also implemented a new QueryElementIndent event that allows you to adjust the indent for specific accordion items based on design preferences/requirements. RIBBON & BARS #PAGE KEY TIPS We added a new ShowPageKeyTipsMode property. Use this property to configure the display of page key tips within the Ribbon UI. This enhancement allows users - who prefer to use keyboard shortcuts instead of mouse input - to quickly navigate through different Ribbon sections and access specific commands (without unnecessary keystrokes). Options include: * Hide - Hides key tips for all Ribbon pages. * ShowOnMultiplePages - Displays key tips only if the Ribbon UI displays multiple pages. * Show (Default) - Displays key tips for all visible Ribbon pages and for the selected page (even if the selected page is hidden). #BARCHECKITEM – CHECKED-STATE IMAGE You can now specify different images (bitmap or SVG) for checked and unchecked states of checkbox items (BarCheckItem). New APIs include: * CheckedImage / CheckedImageIndex / CheckImageKey * CheckedLargeImage / CheckedLargeImageIndex / CheckLargeImageKey * CheckedSVGImage #PRESS ENTER TO EXECUTE A COMMAND We extended available user interactions within the command search box. Users can execute commands without the need for additional clicks or interactions. Handle the new SearchMenuEnterPressed event to execute a command based on freely written text or the first found command instantly when the user performs a search and presses the Enter key. #MANAGE AND DISPLAY RELEVANT COMMANDS WITHIN THE SEARCH MENU POPUP Our Ribbon Control exposes a CustomizeSearchMenu event. This event allows you to implement custom logic to determine which commands must appear in search results. v24.1 extends the event's arguments to simplify customization. New APIs include: * e.AddHeader(string caption) – Displays the header with a specific caption. * e.AddItem(BarItem item) – Displays the specified command in search results. * e.ShowNoMatchesItem – Specifies whether to display “No matches found” when a search query does not return results. * C# void ribbonControl1_CustomizeSearchMenu(object sender, RibbonSearchMenuEventArgs e) { if(e.SearchString.ToLower() == "format") { e.AddHeader("Text Formatting"); e.AddItem(ribbonControl1.Items["iBold"]); e.AddItem(ribbonControl1.Items["iItalic"]); e.AddItem(ribbonControl1.Items["iUnderline"]); e.ShowNoMatchesItem = false; } } We introduced the UseCustomRibbonSearch property for those who prefer to generate search results from scratch. When set to true, our Ribbon Control does not auto-populate search results (e.Menu.ItemLinks). You won't need to clear pre-built search results before adding your own commands. Use the RibbonControl.OptionsSearchMenu property to access search-related settings. These include: * SearchItemPosition * SearchItemShortcut * UseCustomRibbonSearch #MERGE RIBBON MESSAGES (MDI) The Ribbon control of a parent Form displays messages (Office-inspired flyout notifications and alerts) of Ribbon controls displayed on child MDI Forms when merged: Use the RibbonControl.MergedMessages property to access and manage merged messages. DATA EDITORS #DATEEDIT – DATEONLY TYPE SUPPORT Our WinForms DateEdit control now supports the DateOnly data type. The following properties accept DateOnly values: * public DateOnly DateOnly { get; set; } * public object MinDate { get; set; } * public object MaxDate { get; set; } #SIMPLE BUTTON – CUSTOM PAINTING We implemented a new CustomDraw event. Handle this event to paint our WinForms Simple Button manually. * C# void simpleButton1_CustomDraw(object sender, DevExpress.XtraEditors.ButtonCustomDrawEventArgs e) { if(e.Info.State == DevExpress.Utils.Drawing.ObjectState.Hot) { e.Cache.FillRectangle(Brushes.Orange, e.Bounds); e.DefaultDrawImage(); e.DefaultDrawText(); e.Handled = true; } } #UNIFIED PADDING SETTINGS FOR TEXTBOX-BASED EDITORS v24.1 ships with consistent padding settings across all DevExpress Textbox-based data editor types (such as TextEdit, SpinEdit, DateEdit, MemoEdit, etc.). These settings allow you to maintain visual consistency without having to specify different padding options for different editor types. Use Properties.TextPadding and Properties.Padding properties to specify text and content paddings within the text box. #MEMOEDIT – ENHANCED WXI SKIN VISUALIZATION We enhanced the visualization of MemoEdit borders and added scrollbar colorization within our WXI Skin. Accordingly, the DevExpress WinForms MemoEdit now supports DevExpress Skin colors. * C# memoEdit1.Properties.Appearance.BackColor = DevExpress.LookAndFeel.DXSkinColors.FillColors.Question; #DISTINGUISH USER VS. CODE MODIFICATIONS TO THE EDITOR'S VALUE You can now distinguish between modifications made by a user and those made programmatically (in code) to the editor's value. We added a e.ModifiedByUser parameter to arguments for the EditValueChanging event: * C# void textEdit1_EditValueChanging(object sender, DevExpress.XtraEditors.Controls.ChangingEventArgs e) { if(e.ModifiedByUser) { // ... } } DOCUMENT MANAGER #ADDING CONTENT AT DESIGN-TIME Our Document Manager supports deferred loading. To leverage this capability, document content must be generated at runtime in the QueryControl event handler. While this technique offers flexibility and performance benefits, it may be complicated for simple usage scenarios (where all documents are known at design-time). In v24.1, you can add User Controls and Forms to documents at design time (in Visual Studio). DOCKING LIBRARY #LAYOUT RESTORE VALIDATION You can now ensure the integrity and consistency of docking layouts during deserialization. Inconsistency or corruption of deserialized layout data can result in unexpected behavior, visual artifacts, or application crashes. The RestoreLayoutError event allows you to prevent loading of broken layouts or to handle/fix layout-related issues as needed: * C# using DevExpress.Utils.Serializing; void dockManager1_RestoreLayoutError(object sender, RestoreLayoutErrorEventArgs e) { foreach (var exception in e.Exceptions) { if (exception is TabContainerActiveChildNotSetException activeChildException) activeChildException.Panel.ActiveChild = activeChildException.Panels[1]; } e.Throw = false; } Note: we also added layout restore validation in our WinForms Document Manager (RestoreLayoutError). HTML & CSS SUPPORT #PRE-WRITTEN CODE SNIPPETS FOR HTML/CSS v24.1 includes 40 pre-written HTML & CSS code snippets in our HTML Template Designer for Visual Studio. These are optimized code snippets that address common HTML-related tasks. Code snippets include: * Basic Elements (border, picture, link, tooltip, list, table) * Text & Font Snippets * Layout Snippets * Colors & Visual Elements * Binding Snippets #ALIGN EDITOR TEXT You can now use standard CSS properties to align DevExpress editor content (horizontally or vertically) used within HTML templates. PDF VIEWER #SIGNATURE INFO PANEL With our new Signature Info panel, you can display detailed information for each signature in the loaded document and verify signature validity. When you open a document, the PDF Viewer verifies signatures and displays associated status in the Signature panel (valid, invalid, or unknown). In addition, the new panel displays the following signature-related information: * Location of the signature in the document * Signer's information * Reasons the signature was created * Date and time when the document was singed and modified once it was signed * Certificate information. Documentation #LAYERS PDF document layers allow you to selectively view or hide specific content sections. The main purpose of layers is to control the visibility of graphics objects rendered in a PDF document across different states (when you view or print a PDF document). We added a Layers panel to display all layers contained in a document. This new capability allows you to change layer visibility via the UI. Click the check box next to the layer's name in the new Layers panel to display/hide a given document layer. Visible layers are highlighted using an “eye” icon; layers that cannot be hidden because of a document configuration do not have a check box next to their name. With the power of the PDF Facade API, you can also access and manage layer visibility at runtime when you preview or print your PDF documents. Call the PdfViewerExtensions.GetDocumentFacade extension method to obtain the PdfDocumentFacade class object (it allows you to change the PDF document without access to its inner structure) and use the PdfDocumentFacade.OptionalContentVisibility collection to change the visibility state for the required document layers in code. The PdfDocumentFacade class is defined in the DevExpress.Docs.v24.1.dll assembly. Add this assembly to your project or install the DevExpress.Document.Processor NuGet Package to use the PdfDocumentFacade members. You need a license for the DevExpress Office File API Subscription or DevExpress Universal Subscription to use this class in production code. * C# pdfViewer.LoadDocument("layers.pdf"); PdfDocumentFacade documentFacade = pdfViewer.GetDocumentFacade(); // Set visibility for each Layer documentFacade.OptionalContentVisibility.Groups[0].Visible = false; documentFacade.OptionalContentVisibility.Groups[1].Visible = false; documentFacade.OptionalContentVisibility.Groups[2].Visible = true; Documentation RICH TEXT EDITOR #ACCESSIBILITY - SCREEN READERS SUPPORT v24.1 adds support for key accessibility-related requirements, including the ability for assistive technologies (such as screen readers) to read text in the body of a document, alternative text and names for images, text box content, headers, and footers. #EXPORT TO ACCESSIBLE PDF We extended accessibility-related support to the following elements when exporting Word documents to accessible PDF files: * Table of Contents tagging * Metadata fields * Alt text handling * Tables * Floating objects. Adobe Acrobat Pro and PDF Accessibility Checker 2024 were used for quality control. Our test documents successfully passed validation for PDF/UA compatibility and WCAG 2.1 compliance. Accessibility-related export enhancements are available out-of-the-box when you specify the PdfUACompatibility option: * C# using System.IO; using DevExpress.XtraRichEdit; //... using(FileStream stream = new FileStream(resultFilePath, FileMode.Create, FileAccess.Write, FileShare.Read)) { PdfExportOptions exportOptions = new PdfExportOptions(); exportOptions.PdfUACompatibility = PdfUACompatibility.PdfUA1; richEditControl.ExportToPdf(stream, exportOptions); } #DECORATIVE SHAPES We added a Decorative property for the Shape class to mark document graphics (pictures, shapes, and charts) as decorative. Decorative shapes add visual interest, but they are not informative. Thus, you do not need to specify Alt Text (meaningful description) for decorative objects when you generate an accessible document. #MATH EQUATIONS Our Rich Text Editor now preserves Math Equations when saving a document. You can import your Word documents with Math Equations in our WinForms Rich Text Editor and save them to the RTF and OpenXml (.docx/.docm) formats without content loss. Note: Math Equations will be printed or exported to PDF only if the source document contains a fallback image for a Math Equation. To suppress Math Equation import, set the DocumentCapabilities.MathEquations property to DocumentCapability.Disabled. #GUTTER AND MIRRORED MARGINS The DevExpress WinForms Rich Text Editor v24.1 allows you to specify gutter margins - extra space that ensures binding will not obscure text on printed pages. You can specify gutter position (top, left, and right) and margin size. Use the Document.GutterAtTop, SectionMargins.GutterPosition, and SectionMargins.Gutter properties to address specific usage requirements. The following code snippet adds a left gutter to the first document section: * C# using DevExpress.XtraRichEdit; using DevExpress.XtraRichEdit.API.Native; using DevExpress.Office.Utils; //... richEditControl.LoadDocument(@"Documents//Alice.docx"); Document document = richEditControl.Document; Section firstSection = wordProcessor.Document.Sections[0]; var pageMargins = firstSection.Margins; pageMargins.GutterPosition = GutterPosition.Left; pageMargins.Gutter = Units.InchesToDocumentsF(1); richEditControl.SaveDocument("Alice_formatted.docx", DocumentFormat.OpenXml); Our new Document.MarginType property allows you to define a regular or mirrored margin type. Enable mirrored margins if you print on both sides of the paper and want to bind the printout. The following code snippet enables mirrored margins and specifies an additional space value: * C# using DevExpress.XtraRichEdit; using DevExpress.XtraRichEdit.API.Native; using DevExpress.Office.Utils; //... richEditControl.LoadDocument(@"Documents//Alice.docx"); Document document = richEditControl.Document; // Enable mirrored margins document.MarginsType = MarginsType.Mirrored; foreach (Section section in richEditControl.Document.Sections) { var pageMargins = section.Margins; // Set the value for mirrored margins pageMargins.Gutter = Units.InchesToDocumentsF(0.5f); } richEditControl.SaveDocument("Alice_formatted.docx", DocumentFormat.OpenXml); New UI elements are also available. Documentation #IMAGE EXPORT API v24.1 includes new cross-platform APIs to export Word document pages to an image. This new capability allows you to generate document previews. With our new APIs, you can convert document pages to raster and vector images (PNG, JPEG, BMP, multi-page Tiff, emf), save them as physical files on the disk or obtain a list of image streams for further processing in code. You can also set image background color, modify output image resolution, or generate thumbnail images with a specified size. The new API is available via the RichEditDocumentServerExtensions.ExportToImage extension method of the Document object. Please note that the RichEditDocumentServerExtensions class is defined in the DevExpress.Docs.v24.1.dll assembly. Add this assembly to your project or install the "DevExpress.Document.Processor" NuGet Package to use the RichEditDocumentServerExtensions members. You need a license for the DevExpress Office File API Subscription or DevExpress Universal Subscription to use this class in production code. The following code snippet exports the first document page to an image with a specified size and JPEG format: * C# using DevExpress.XtraRichEdit; using DevExpress.XtraRichEdit.Export.Image; using DevExpress.Drawing; richEditControl.LoadDocument(@"C:\Documents\Alice.docx"); //... RichEditImageExportOptions options = new RichEditImageExportOptions(); options.Format = DXImageFormat.Jpeg; options.PageRange = "1"; options.LargestEdgeLength = 1080; richEditControl.Document.ExportToImage(@"C:\Documents\Image.jpeg", options); #EXPORT DOCUMENT PAGES TO SVG Our new Image Export APIs allow you to export document pages to SVG. Use the RichEditImageExportOptions.Format option to set SVG as a target image format. * C# RichEditImageExportOptions options = new RichEditImageExportOptions(); options.Format = DXImageFormat.Svg; options.PageRange = "1"; richEditControl.Document.ExportToImage(@"C:\Documents\Image.svg", options); SVG Export is also available from the user interface - open the Print Preview dialog, click the Export to Image button, choose the SVG format in the Image Options dialog and complete document export. SVG SCROLL CURSOR WinForms data-aware controls with scrollable content now ship with DPI-independent scroll cursor (the cursor that appears when the user presses the middle mouse button), providing smooth and precise navigation regardless of screen resolution. SPREADSHEET #ACCESSIBILITY ENHANCEMENTS - DECORATIVE SHAPES We added a Decorative property for the Shape class to mark document graphics (pictures, shapes and charts) as decorative. Decorative shapes add visual interest, but they are not informative. Thus, you do not need to specify Alt Text (meaningful description) for decorative objects when you generate an accessible document. #JUSTIFY & DISTRIBUTED TEXT ALIGNMENT v24.1 adds support for Justify and Distributed horizontal alignment types within Spreadsheet cells. Excel files using these alignment options can be printed and exported to PDF. You can use the Cell.Alignment.Horizontal property to specify horizontal alignment in code. The following code snippet specifies alignment in code: * C# var workbook = new Workbook(); var worksheet = workbook.Worksheets[0]; Cell cellA1 = worksheet.Cells["A1"]; cellA1.Value = "Justified and top"; cellA1.Alignment.Horizontal = SpreadsheetHorizontalAlignment.Justify; cellA1.Alignment.Vertical = SpreadsheetVerticalAlignment.Top; workbook.ExportToPdf("Result.pdf"); #SORT AND FILTER BY COLOR The DevExpress WinForms Spreadsheet ships with enhanced filter and sort-related capabilities. We added new APIs that can sort and filter workbook data by background and font color. Cell ranges filtered/sorted by cell color can also be printed and exported to PDF. Our Sorting APIs include new Worksheet.Sort method overloads designed to sort a specified range by font color or fill setting (background color and pattern). The following code snippet sorts cell values across two cell ranges - the first is sorted by a red font color and the second is sorted by fill settings specified for the first cell in the range: * C# spreadsheetControl.LoadDocument("sort-filter.xlsx"); Worksheet worksheet = spreadsheetControl.ActiveWorksheet; // Sort cell range by font color worksheet.Sort(worksheet["B2:B10"], Color.Red); // Sort cell range by fill color worksheet.Sort(worksheet["D2:D10"], worksheet["D2"].Fill); To filter cells by font or background color, you need to apply an auto-filter to the required cell range or table. Once complete, you need to obtain the required column from the AutoFilter.Columns collection and call one of the following methods: * AutoFilterColumn.ApplyFillColorFilter(Color) * AutoFilterColumn.ApplyFillFilter(Fill) * AutoFilterColumn.ApplyFontColorFilter(Color) The following code snippet uses these methods for both cell range and table: * C# spreadsheetControl.LoadDocument("sort-filter.xlsx"); Worksheet worksheet = spreadsheetControl.ActiveWorksheet; // Apply an auto-filter to a cell range and filter the first column by font color worksheet.AutoFilter.Apply(worksheet["B1:B10"]); worksheet.AutoFilter.Columns[0].ApplyFontColorFilter(Color.Red); // Create a table, apply an auto-filter and filter the first column by fill color Table table = worksheet.Tables.Add(worksheet["B12:B21"], true); table.AutoFilter.Apply(); table.AutoFilter.Columns[0].ApplyFillColorFilter(Color.Red); In addition, our new APIs allow you to sort data across a filtered range (when auto-filter is enabled) and sort cells by their values/colors simultaneously (using sorting conditions). Documentation: Sort Cell Range by Color #EXPORT CELL RANGE TO SVG In this release, we enhanced our CellRangeExtensions.ExportToImage method and added support for the SVG image format. The CellRangeExtensions class is defined in the DevExpress.Docs.v24.1.dll assembly. Add this assembly to your project or install the DevExpress.Document.Processor NuGet Package to use CellRangeExtensions members. To use this class in production code, you will need an active DevExpress Office File API or DevExpress Universal Subscription. * C# spreadsheetControl.LoadDocument("InvestmentPortfolio.xlsx", DocumentFormat.Xlsx); Worksheet worksheet = spreadsheetControl.ActiveWorksheet; worksheet.Range["B18:I30"].ExportToImage("cell_range_image.svg", ImageFileFormat.Svg); SVG Export is also available from the user interface - open the Print Preview dialog, click the Export to Image button, choose the SVG format in the Image Options dialog and complete document export. ACCESSIBILITY AND UI AUTOMATION #ACCESSIBLE KEYBOARD NAVIGATION TabPane & NavigationPane We added keyboard navigation support to our WinForms TabPane and Navigation Pane controls (much like that of the XtraTabControl). Keyboard focus is now managed as follows: * Right/Left Arrow — Activates the Next/Previous page. * Ctrl+Tab / Ctrl+Shift+Tab — Activates the Next/Previous page and focuses the tab header or UI control displayed on the page. * Home — Activates the first page. * End — Activates the last page. Additional API includes: * AllowNavigationThroughPages — Activate this option to focus the tab header (rather than the UI control displayed on the page) when the user navigates using the Tab key. This option is disabled by default. * ShowHeaderFocus — Displays/hides the focus rectangle. TextBox-based Data Editors in BarEditItems We improved keyboard navigation within our Ribbon UI and Toolbars. Keyboard focus is now appropriately managed to mimic behaviors found in Microsoft Word. Specifically, when the BarEditItem has focus and the user presses an arrow key, the BarEditItem retains focus, allowing navigation within the editor. v24.1 exposes new properties that allow you to suppress a keyboard key (Alt or Control) for bar items with embedded editors (BarEditItem): * BarManager.SuppressModifierKey — This global setting specifies the behavior for all BarEditItems within the Form. * BarEditItem.SuppressModifierKey — Specifies the behavior for a specific BarEditItem. The following example activates MS Word-inspired behavior for a bar item with a combo box. Instead of using the Alt+DownArrow combination to open the dropdown, the user simply needs to press DownArrow: * C# public Form1() { InitializeComponent(); barItemCombobox.SuppressModifierKey = DevExpress.XtraEditors.SuppressKeys.Alt; } ButtonEdit-based Editors We've optimized the keyboard focus within our ButtonEdit-related controls to ensure that it follows a logical and intuitive sequence. Users can easily tab from the edit box to buttons, navigate through buttons using Left/Right keys, press buttons (Enter/Space), and tab back to the edit box (Escape or Shift+Tab). Use the WindowsFormsSettings.KeyboardNavigationExtension property to enable this behavior for DevExpress TabPane, NavigationPane, and all ButtonEdit controls within the application. * C# public Form1() { InitializeComponent(); DevExpress.XtraEditors.WindowsFormsSettings.KeyboardNavigationExtensions = DevExpress.XtraEditors.KeyboardNavigationExtensions.All; } Use the AllowButtonNavigation property to enable keyboard navigation for a specific ButtonEdit control. Additional options include: * In-place Mode Support * Right to Left Mode Support * Advanced Mode Support WinForms TileView (Kanban) End-users can now focus tile group header/footer buttons with the keyboard and use arrow keys for left/right navigation. WinForms Diagram Control We improved keyboard navigation in the DevExpress WinForms Diagram control. Users can now use the following keyboard keys: * Ctrl++ – Zooms in on the canvas. * Ctrl+- – Zooms out the canvas. * Ctrl+Space – Expands/collapses the focused container. * F4 – Opens the Properties window. Column Filter Popup When a user opens an Excel Filter Popup, the popup window automatically receives focus. Users can navigate between popup window UI elements using the keyboard. #SCREEN READER RELATED ENHANCEMENTS v24.1 ships with improved accessibility across our WinForms UI control library. Screen readers (such as Narrator and NVDA) can now pronounce the following user actions and properties: * Checking an item in the Data Grid Column Customization Menu. * Expanding/collapsing an item in the DevExpress Accordion Control. * Specifying criteria within the DevExpress Grid Auto Filter Row. * Focusing tokens in the Token Editor (a Screen reader pronounces tokes). * Focusing a group in the DevExpress WinExplorer View. * Focusing a cell in the DevExpress Grid New Item Row. * Navigating through card fields in the DevExpress CardView. * TextEdit.Properties.AdvancedModeOptions.Label * TextEdit.Properties.NullValuePrompt Additional enhancements: * When a user enters an incorrect expression in the Expression Editor, the screen reader pronounces the error message. * When a user uses the integrated Find Panel to search for specific information, the screen reader pronounces the number of search results. #ACCESSKEY AND ACCELERATORKEY SUPPORT IN RIBBON UI AND TOOLBARS Ribbon UI elements (Bar items, Ribbon pages, BackStageView, Group Caption button, and Application button) now expose the following accessibility-related properties: * AccessKey in MSAA and UI Automation * AcceleratorKey in UI Automation. Note: We set these properties based on values of properties such as ItemShortcut. MISCELLANEOUS ENHANCEMENTS #ASSIGN IMAGES BY KEY/NAME Image options include a new ImageKey string setting. Use it to specify an image by its "name". Unlike ImageIndex, where adding or removing images can change the position of existing images in the collection (requiring the ImageIndex property to be updated), the ImageKey property identifies an image regardless of its position in the collection (search in the collection is done by the image name). Note: ImageKey takes priority over ImageIndex (if both properties are specified). PERFORMANCE IMPROVEMENTS #IMPROVED WINDOWS FORMS OUT-OF-PROCESS DESIGNER We were in close collaboration with the Microsoft dev team over the last few months, and Microsoft has recently released a Visual Studio 2022 update, which improves form load performance across a number of .NET Core / .NET usage scenarios. These performance enhancements are not tied to any DevExpress version because they are implemented at the Visual Studio core level (based on our feedback associated with problematic internal routines). From Microsoft release notes: Through a fruitful collaboration with a key partner, we are thrilled to announce substantial enhancements to the WinForms server process TypeResolutionService. These enhancements have yielded remarkable design time performance improvements, ranging from 30% to an impressive 50% in typical line of business applications. Notably, these enhancements particularly shine during scenarios that trigger server process restart and designer reload, such as project rebuilds or adjustments in project references. At the heart of these performance improvements lies a new mechanism implemented by our team, prioritizing assemblies crucial for designer load. We encourage you to explore the updated designer and share your invaluable feedback through VS Feedback channel so that we can continue improving WinForms designer performance. You can cut an additional 1-2 seconds from designer startup (if you do not need all DevExpress WinForms components simultaneously on your forms) by using the following smaller packages (like DevExpress.Win.Grid, DevExpress.Win.TreeList, DevExpress.Win.Charts, etc.) instead of the large DevExpress.Win.Design package. Read the Blog Post SURVEY - WINFORMS YOUR FEEDBACK MATTERS! Please login to complete the survey. SURVEY COMPLETED Thank you for taking the time to complete this survey. Your responses have now been posted. If you want to follow up with additional information, feel free to send us an email at clientservices@devexpress.com anytime. YOU'VE ALREADY COMPLETED THIS SURVEY Our records show that you have already completed this survey. If you want to follow up with additional information, send us an email at clientservices@devexpress.com. THIS SURVEY HAS EXPIRED If you want to share your feedback or request new functionality, please submit a new support ticket via the DevExpress Support Center. We’ll be happy to follow up. WPF CONTROLS V24.1 Accessibility and UI Automation DateOnly & TimeOnly Type Support Data Grid Font Icon Images Ribbon & Bars PDF Viewer Rich Text Editor Property Grid Spreadsheet Lightweight Themes Survey - WPF Your feedback matters. Please, review the description of WPF-related features below and leave your feedback at the end of the section. Go to the survey now. ACCESSIBILITY AND UI AUTOMATION #ASSISTIVE TECHNOLOGIES (SCREEN READERS) – COMPATIBILITY ENHANCEMENTS We enhanced our WPF Accessibility Tree for the following UI controls (assistive technologies obtain the necessary information to help address WCAG accessibility guidelines): * Layout Control * Tab Control * Ribbon Gallery * Built-in Dialogs and Forms (such as Column Filter Popup, Bars Customization Window). Screen readers (such as Narrator and NVDA) can now pronounce the following actions: * The user selects a row/node with the keyboard in the DevExpress WPF Grid or WPF TreeList control. * The user expands/collapses a node. * The user checks/unchecks a node. * The user moves focus to a WPF Ribbon Bar item. * The WPF Grid’s cell value is modified in code. Screen readers can now access the following information: * Column/band name for the focused WPF Grid cell. * Focused WPF Grid row cell values in multi row selection mode. * The position of the focused cell among visible rows/columns. * The name of the New Item Row in DevExpress WPF Grid and TreeList controls. * Active cell editor type in the DevExpress WPF Grid. * DevExpress WPF ThemedMessageBox text. * DevExpress WPF Step Progress Bar items. #ACCESSIBLE KEYBOARD NAVIGATION WPF Diagram Control We improved keyboard navigation in the DevExpress WPF Diagram control. Users can now use the following keyboard keys: * Ctrl++ – Zooms in on the canvas. * Ctrl+- – Zooms out the canvas. * Ctrl+Space – Expands/collapses the focused container. * F4 – Opens the Properties window. WPF Ribbon Control We improved keyboard navigation within our WPF Ribbon control. Users can move focus to the "Expand/Collapse Ribbon" button using the Tab or Arrow key (Space and Enter keys expand/collapse the Ribbon). v24.1 ships with improved keyboard navigation within BarSplitButtonItem: * Enter – Executes the main action. * Alt + DownArrow – Invokes the drop-down window. Row Context Menus in the WPF Grid Control Pressing the Context Menu Button invokes a context menu for the focused row. WPF Office Navigation Bar Users can now press Space or Enter to invoke an action associated with the focused item. WPF Accordion Control Pressing the Shift+Tab shortcut focuses the "Expand/Collapse" button. WPF Track Bar Editor Users can now focus each thumb of the range track bar editor with the keyboard. DATEONLY & TIMEONLY TYPE SUPPORT DevExpress WPF Data Grid now supports DateOnly and TimeOnly data types (in .NET applications). These data types offer the following advantages (versus the traditional DateTime type): usage clarity, improved database compatibility, less space during serialization, and the ability to mitigate potential errors/inconsistencies related to different time zones. Built-in DateOnly/TimeOnly support extends to: * UI Elements Related to Data Filtering (Column Filter Popup, Filter Editor, Expression Editor, Automatic Filter Row) * Conditional Formatting Rules * Data Summaries * Data Grouping * Unbound Columns * Criteria Operators * Masks * Search DATA GRID #EXPORT CELL IMAGES TO EXCEL The WPF Data Grid now exports images (raster and SVG) displayed within cells of bound and unbound columns to XLSX format in data-aware export mode. Cell images are exported as a Byte[] array. To activate this feature, set the AllowCellImages property to DefaultBoolean.True. * C# XlsxExportOptionsEx options = new XlsxExportOptionsEx(); options.AllowCellImages = DevExpress.Utils.DefaultBoolean.True; view.ExportToXlsx("grid_export.xlsx", options); Handle the CustomizeCell event to customize cell images or replace values with images (based on export conditions) before the Grid Control generates the output document. Documentation #FILTER BY COLOR AND ICON SET We extended the user experience when using the WPF Grid Control (in TableView and TreeListView). Users can quickly filter data based on visual criteria (Icon Set and Color Scale format conditions). This functionality is available to users via the column header's context menu if conditional formatting is applied: New APIs include: * TableView.AllowFormatConditionFiltersMenu – Displays/hides the “Format Condition Filters” submenu in context menus associated with all columns in a TableView (if conditional formatting is applied). * TreeListView.AllowFormatConditionFiltersMenu – Displays/hides the “Format Condition Filters” submenu in context menus associated with all columns in a TreeListView (if conditional formatting is applied). * AllowFormatConditionFiltersMenu – Displays/hides the “Format Condition Filters” submenu in the context menu associated with a specific column (if conditional formatting is applied). #AGGREGATE FILTERS We added aggregate filter support to our WPF Data Grid. The Data Grid exposes a new AllowFilterEditorAggregateOperands property that allows users to filter data by items in bound collection data fields (for example, master-detail data). When enabled, the grid Filter Editor displays aggregated operands for collection properties/fields (SUM, COUNT, MIN, MAX, AVG, EXISTS). You can also customize the operand list (for example, hide unnecessary operands) for specific data columns using the AllowedAggregateFilters property. * XAML <dxg:GridColumn FieldName="Genres" AllowedAggregateFilters="Exists, Count"/> FONT ICON IMAGES Support for Font Icon Images was first introduced in our WinForms product line (Dec 2023). v24.1 extends this feature to our WPF UI library. Use the DevExpress WPF Image Picker (integrated within Visual Studio) to assign font icon images to individual UI controls/elements or use our FontIconSource extension to do the same in code. If you execute a DevExpress-powered WPF application, it will display icons from the most recent icon font available in the system. For example, the "Segoe Fluent Icons" font is used as the default font if both "Segoe Fluent Icons" and "Segoe MDL2 Assets" fonts are installed. Use the FontIconSourceExtension.FontFamily property to specify icon font: * XAML <dxb:BarButtonItem Glyph="{dx:FontIconSource Glyph=0xf0b4, FontFamily=SegoeMDL2Assets}"/> You can also select an icon color from predefined values (Red, Green, Blue, Yellow, Black, and White). These colors are auto modified to match the applied DevExpress Theme: * XAML <dxb:BarButtonItem Glyph="{dx:FontIconSource Glyph=59246, ColorName=Yellow}"/> And yes, you can use WpfSvgPalette to colorize icons to address design preferences: * XAML <dxb:BarButtonItem Glyph="{dx:FontIconSource Glyph=59246}"> <dx:WpfSvgPalette.Palette> <dx:WpfSvgPalette> <SolidColorBrush x:Key="Black" Color="Aqua"/> </dx:WpfSvgPalette> </dx:WpfSvgPalette.Palette> </dxb:BarButtonItem> Documentation: Font Icon Images RIBBON & BARS #SEARCH BOX A Ribbon-based UI can include dozens of commands across multiple pages. Without prior experience with a given app, users can struggle to locate appropriate actions/commands. To minimize usage friction/learning curve, v24.1 ships with a new WPF Ribbon Search Box. Specify the SearchItemDisplayMode property to activate the search box in your WPF app. Our WPF Ribbon compares the search string to command content (BarButtonItem.Content) to generate search results. You can enable an item's HideFromSearch option to exclude it from search. For more granular control, use the following events: * ItemsRequested – Fires when the searchable items list is generated. The event allows you to modify search results before applying the search criteria (for example, to add additional items based on a condition). * ItemFiltering – Fires for each item before it is displayed in search results. The event allows you to hide the item from search results. * ItemsFiltered – Notifies when a search is complete. Additional settings include: * SearchDelay – Specifies the delay in milliseconds between the last text change and the text search. * SearchItemFocusShortcut – Specifies the keyboard shortcut used to focus the search box (the default shortcut is "Ctrl+F"). * ShowDescriptionInSearchResults - Specifies whether to display the path to items within the DevExpress WPF Ribbon UI (Category > Page > Group). Run Demo To execute this demo, you must first install the DevExpress WPF product library . PDF VIEWER #SIGNATURE INFO PANEL With our new Signature Info panel, you can display detailed information for each signature in the loaded document and verify signature validity. When you open a document, the PDF Viewer verifies signatures and displays associated status in the Signature panel (valid, invalid, or unknown). In addition, the new panel displays the following signature-related information: * Location of the signature in the document * Signer's information * Reasons the signature was created * Date and time when the document was singed and modified once it was signed * Certificate information. Documentation #LAYERS PDF document layers allow you to selectively view or hide specific content sections. The main purpose of layers is to control the visibility of graphics objects rendered in a PDF document across different states (when you view or print a PDF document). We added a Layers panel to display all layers contained in a document. This new capability allows you to change layer visibility via the UI. Click the check box next to the layer's name in the new Layers panel to display/hide a given document layer. Visible layers are highlighted using an “eye” icon; layers that cannot be hidden because of a document configuration do not have a check box next to their name. With the power of the PDF Facade API, you can also access and manage layer visibility at runtime when you preview or print your PDF documents. Call the PdfViewerExtensions.GetDocumentFacade extension method to obtain the PdfDocumentFacade class object (it allows you to change the PDF document without access to its inner structure) and use the PdfDocumentFacade.OptionalContentVisibility collection to change the visibility state for the required document layers in code. The PdfDocumentFacade class is defined in the DevExpress.Docs.v24.1.dll assembly. Add this assembly to your project or install the DevExpress.Document.Processor NuGet Package to use the PdfDocumentFacade members. You need a license for the DevExpress Office File API Subscription or DevExpress Universal Subscription to use this class in production code. * C# pdfViewer.LoadDocument("layers.pdf"); PdfDocumentFacade documentFacade = pdfViewer.GetDocumentFacade(); // Set visibility for each Layer documentFacade.OptionalContentVisibility.Groups[0].Visible = false; documentFacade.OptionalContentVisibility.Groups[1].Visible = false; documentFacade.OptionalContentVisibility.Groups[2].Visible = true; Documentation RICH TEXT EDITOR #EXPORT TO ACCESSIBLE PDF We extended accessibility-related support to the following elements when exporting Word documents to accessible PDF files: * Table of Contents tagging * Metadata fields * Alt text handling * Tables * Floating objects. Adobe Acrobat Pro and PDF Accessibility Checker 2024 were used for quality control. Our test documents successfully passed validation for PDF/UA compatibility and WCAG 2.1 compliance. Accessibility-related export enhancements are available out-of-the-box when you specify the PdfUACompatibility option: * C# using System.IO; using DevExpress.XtraRichEdit; //... using(FileStream stream = new FileStream(resultFilePath, FileMode.Create, FileAccess.Write, FileShare.Read)) { PdfExportOptions exportOptions = new PdfExportOptions(); exportOptions.PdfUACompatibility = PdfUACompatibility.PdfUA1; richEditControl.ExportToPdf(stream, exportOptions); } #DECORATIVE SHAPES We added a Decorative property for the Shape class to mark document graphics (pictures, shapes, and charts) as decorative. Decorative shapes add visual interest, but they are not informative. Thus, you do not need to specify Alt Text (meaningful description) for decorative objects when you generate an accessible document. #MATH EQUATIONS Our Rich Text Editor now preserves Math Equations when saving a document. You can import your Word documents with Math Equations in our WinForms Rich Text Editor and save them to the RTF and OpenXml (.docx/.docm) formats without content loss. Note: Math Equations will be printed or exported to PDF only if the source document contains a fallback image for a Math Equation. To suppress Math Equation import, set the DocumentCapabilities.MathEquations property to DocumentCapability.Disabled. #GUTTER AND MIRRORED MARGINS The DevExpress WPF Rich Text Editor v24.1 allows you to specify gutter margins - extra space that ensures binding will not obscure text on printed pages. You can specify gutter position (top, left, and right) and margin size. Use the Document.GutterAtTop, SectionMargins.GutterPosition, and SectionMargins.Gutter properties to address specific usage requirements. The following code snippet adds a left gutter to the first document section: * C# using DevExpress.XtraRichEdit; using DevExpress.XtraRichEdit.API.Native; using DevExpress.Office.Utils; //... richEditControl.LoadDocument(@"Documents//Alice.docx"); Document document = richEditControl.Document; Section firstSection = wordProcessor.Document.Sections[0]; var pageMargins = firstSection.Margins; pageMargins.GutterPosition = GutterPosition.Left; pageMargins.Gutter = Units.InchesToDocumentsF(1); richEditControl.SaveDocument("Alice_formatted.docx", DocumentFormat.OpenXml); Our new Document.MarginType property allows you to define a regular or mirrored margin type. Enable mirrored margins if you print on both sides of the paper and want to bind the printout. The following code snippet enables mirrored margins and specifies an additional space value: * C# using DevExpress.XtraRichEdit; using DevExpress.XtraRichEdit.API.Native; using DevExpress.Office.Utils; //... richEditControl.LoadDocument(@"Documents//Alice.docx"); Document document = richEditControl.Document; // Enable mirrored margins document.MarginsType = MarginsType.Mirrored; foreach (Section section in richEditControl.Document.Sections) { var pageMargins = section.Margins; // Set the value for mirrored margins pageMargins.Gutter = Units.InchesToDocumentsF(0.5f); } richEditControl.SaveDocument("Alice_formatted.docx", DocumentFormat.OpenXml); New UI elements are also available. Documentation #IMAGE EXPORT API v24.1 includes new cross-platform APIs to export Word document pages to an image. This new capability allows you to generate document previews. With our new APIs, you can convert document pages to raster and vector images (PNG, JPEG, BMP, multi-page Tiff, emf), save them as physical files on the disk or obtain a list of image streams for further processing in code. You can also set image background color, modify output image resolution, or generate thumbnail images with a specified size. The new API is available via the RichEditDocumentServerExtensions.ExportToImage extension method of the Document object. Please note that the RichEditDocumentServerExtensions class is defined in the DevExpress.Docs.v24.1.dll assembly. Add this assembly to your project or install the "DevExpress.Document.Processor" NuGet Package to use the RichEditDocumentServerExtensions members. You need a license for the DevExpress Office File API Subscription or DevExpress Universal Subscription to use this class in production code. The following code snippet exports the first document page to an image with a specified size and JPEG format: * C# using DevExpress.XtraRichEdit; using DevExpress.XtraRichEdit.Export.Image; using DevExpress.Drawing; richEditControl.LoadDocument(@"C:\Documents\Alice.docx"); //... RichEditImageExportOptions options = new RichEditImageExportOptions(); options.Format = DXImageFormat.Jpeg; options.PageRange = "1"; options.LargestEdgeLength = 1080; richEditControl.Document.ExportToImage(@"C:\Documents\Image.jpeg", options); #EXPORT DOCUMENT PAGES TO SVG Our new Image Export APIs allow you to export document pages to SVG. Use the RichEditImageExportOptions.Format option to set SVG as a target image format. * C# RichEditImageExportOptions options = new RichEditImageExportOptions(); options.Format = DXImageFormat.Svg; options.PageRange = "1"; richEditControl.Document.ExportToImage(@"C:\Documents\Image.svg", options); SVG Export is also available from the user interface - open the Print Preview dialog, click the Export to Image button, choose the SVG format in the Image Options dialog and complete document export. PROPERTY GRID #CUSTOMIZE ROW APPEARANCE We added a PropertyGridControl.RowStyle property. Use this property to customize row appearance/style settings. As you would expect from a DevExpress WPF grid-based control, you have full control over row appearance. You can apply row styles based on a condition (use the WPF PropertyGrid's RowStyleSelector property or standard WPF trigger-based techniques), or you can use the new AlternationCount property to alternate row styles. * XAML <dxprg:PropertyGridControl ... AlternationCount="3"> <dxprg:PropertyGridControl.RowStyle> <Style TargetType="dxprg:RowControl"> <Style.Triggers> <Trigger Property="ItemsControl.AlternationIndex" Value="1"> <Setter Property="Background" Value="#122C2C2C"/> </Trigger> <Trigger Property="ItemsControl.AlternationIndex" Value="2"> <Setter Property="Background" Value="LightGray"/> </Trigger> </Style.Triggers> </Style> </dxprg:PropertyGridControl.RowStyle> </dxprg:PropertyGridControl> SPREADSHEET #ACCESSIBILITY ENHANCEMENTS - DECORATIVE SHAPES We added a Decorative property for the Shape class to mark document graphics (pictures, shapes and charts) as decorative. Decorative shapes add visual interest, but they are not informative. Thus, you do not need to specify Alt Text (meaningful description) for decorative objects when you generate an accessible document. #JUSTIFY & DISTRIBUTED TEXT ALIGNMENT v24.1 adds support for Justify and Distributed horizontal alignment types within Spreadsheet cells. Excel files using these alignment options can be printed and exported to PDF. You can use the Cell.Alignment.Horizontal property to specify horizontal alignment in code. The following code snippet specifies alignment in code: * C# var workbook = new Workbook(); var worksheet = workbook.Worksheets[0]; Cell cellA1 = worksheet.Cells["A1"]; cellA1.Value = "Justified and top"; cellA1.Alignment.Horizontal = SpreadsheetHorizontalAlignment.Justify; cellA1.Alignment.Vertical = SpreadsheetVerticalAlignment.Top; workbook.ExportToPdf("Result.pdf"); #SORT AND FILTER BY COLOR The DevExpress WPF Spreadsheet ships with enhanced filter and sort-related capabilities. We added new APIs that can sort and filter workbook data by background and font color. Cell ranges filtered/sorted by cell color can also be printed and exported to PDF. Our Sorting APIs include new Worksheet.Sort method overloads designed to sort a specified range by font color or fill setting (background color and pattern). The following code snippet sorts cell values across two cell ranges - the first is sorted by a red font color and the second is sorted by fill settings specified for the first cell in the range: * C# spreadsheetControl.LoadDocument("sort-filter.xlsx"); Worksheet worksheet = spreadsheetControl.ActiveWorksheet; // Sort cell range by font color worksheet.Sort(worksheet["B2:B10"], Color.Red); // Sort cell range by fill color worksheet.Sort(worksheet["D2:D10"], worksheet["D2"].Fill); To filter cells by font or background color, you need to apply an auto-filter to the required cell range or table. Once complete, you need to obtain the required column from the AutoFilter.Columns collection and call one of the following methods: * AutoFilterColumn.ApplyFillColorFilter(Color) * AutoFilterColumn.ApplyFillFilter(Fill) * AutoFilterColumn.ApplyFontColorFilter(Color) The following code snippet uses these methods for both cell range and table: * C# spreadsheetControl.LoadDocument("sort-filter.xlsx"); Worksheet worksheet = spreadsheetControl.ActiveWorksheet; // Apply an auto-filter to a cell range and filter the first column by font color worksheet.AutoFilter.Apply(worksheet["B1:B10"]); worksheet.AutoFilter.Columns[0].ApplyFontColorFilter(Color.Red); // Create a table, apply an auto-filter and filter the first column by fill color Table table = worksheet.Tables.Add(worksheet["B12:B21"], true); table.AutoFilter.Apply(); table.AutoFilter.Columns[0].ApplyFillColorFilter(Color.Red); In addition, our new APIs allow you to sort data across a filtered range (when auto-filter is enabled) and sort cells by their values/colors simultaneously (using sorting conditions). Documentation: Sort Cell Range by Color #EXPORT CELL RANGE TO SVG In this release, we enhanced our CellRangeExtensions.ExportToImage method and added support for the SVG image format. The CellRangeExtensions class is defined in the DevExpress.Docs.v24.1.dll assembly. Add this assembly to your project or install the DevExpress.Document.Processor NuGet Package to use CellRangeExtensions members. To use this class in production code, you will need an active DevExpress Office File API or DevExpress Universal Subscription. * C# spreadsheetControl.LoadDocument("InvestmentPortfolio.xlsx", DocumentFormat.Xlsx); Worksheet worksheet = spreadsheetControl.ActiveWorksheet; worksheet.Range["B18:I30"].ExportToImage("cell_range_image.svg", ImageFileFormat.Svg); SVG Export is also available from the user interface - open the Print Preview dialog, click the Export to Image button, choose the SVG format in the Image Options dialog and complete document export. LIGHTWEIGHT THEMES #OBTAIN LIGHTWEIGHT THEME PALETTE COLOR With v24.1, you can effortlessly access color information from existing palettes that ship as part of our Lightweight themes. This functionality extends to custom color palettes, allowing you to use colors that reflect the unique identity of your WPF application. Documentation SURVEY - WPF YOUR FEEDBACK MATTERS! Please login to complete the survey. SURVEY COMPLETED Thank you for taking the time to complete this survey. Your responses have now been posted. If you want to follow up with additional information, feel free to send us an email at clientservices@devexpress.com anytime. YOU'VE ALREADY COMPLETED THIS SURVEY Our records show that you have already completed this survey. If you want to follow up with additional information, send us an email at clientservices@devexpress.com. THIS SURVEY HAS EXPIRED If you want to share your feedback or request new functionality, please submit a new support ticket via the DevExpress Support Center. We’ll be happy to follow up. JAVASCRIPT & ASP.NET CORE COMPONENTS V24.1 New Splitter Component UI/UX and API Enhancements JS Script Size Angular 18 Support New DxHttpModule for Angular Shadow DOM Support (CTP) Accessibility ASP.NET Core - DateOnly/TimeOnly Type Support ASP.NET Core - Data Validation ASP.NET Core - Rich Text Editor Survey - JavaScript & ASP.NET Core Your feedback matters. Please, review the description of JavaScript and ASP.NET Core related features below and leave your feedback at the end of the section. Go to the survey now. NEW SPLITTER COMPONENT Our new Splitter component allows you to divide a page or section into multiple adjustable panes. These panes can be: * resizable - A handle with a drag icon allows users to modify size. * collapsible - A handle with an arrow icon allows users to collapse the pane. If you enable both these properties, the handle displays both icons and users can both resize/collapse a given pane as desired. If both properties are false, the handle remains hidden. The Splitter component can be oriented either vertically or horizontally. Orientation affects the following pane-related properties (can be specified in pixels or percents) * size - Specifies initial width (horizontal orientation) or height (vertical) of the pane. * maxSize, minSize - Defines resizing limits for the pane. * collapsedSize - Specifies the size of a collapsible pane when collapsed. * Angular * React * Vue * jQuery <dx-splitter orientation="vertical"> <dxi-item [collapsible]="true" size="50%" minSize="20px" сollapsedSize="30px" > </dxi-item> </dx-splitter> const App = () => ( <Splitter orientation="vertical"> <Item collapsible={true} size="50%" minSize="20px" сollapsedSize="30px" /> </Splitter> ); export default App; <template> <DxSplitter orientation="vertical"> <DxItem :collapsible="true" size="50%" min-size="20px" collapsed-size="30px" /> </DxSplitter> </template> $('#splitter').dxSplitter({ orientation: 'vertical', items: [ { collapsible: true, size: '50%', minSize: '20px', collapsedSize: '30px', }, ], }); Splitter panes can contain multiple content types, ranging from simple HTML to complex components. You can place HTML markup inside the item tag or use the following properties to populate panes with content: * itemTemplate - Defines a custom template for all panes. * template - Sets a custom template for each specific pane. To customize Splitter appearance, specify the separatorSize property to modify the size of the handle's shorter side. You can also alter color and icons through CSS. Enable allowKeyboardNavigation in the Splitter component to control Splitter actions through shortcut keys, mirroring mouse functions. To see the full list of shortcuts, refer to the following help topic: Accessibility. For complex layouts, nest Splitters as illustrated in our demo (which also highlights use of templates for content insertion). Select one of the following supported dev frameworks to explore the capabilities of this new feature: Angular | React | Vue | jQuery | ASP.NET Core | ASP.NET MVC UI/UX AND API ENHANCEMENTS #DROPDOWNBUTTON - CUSTOM BUTTON TEMPLATE With v24.1, you can replace the base button in DropDownButton with custom content (such as an avatar or multiline text). * Angular * React * Vue * jQuery <dx-drop-down-button icon="spindown" template="button-template"> <div *dxTemplate="let data of 'button-template'"> <div class="text-container"> <div class="name"> {{ currentEmployee.FirstName }} {{ currentEmployee.LastName }} </div> <div class="position"> {{ currentEmployee.Position }} </div> </div> <span class="dx-icon-{{ data.icon }} dx-icon"></span> </div> </dx-drop-down-button> const renderButton = (data) => { return ( <React.Fragment> <div className="text-container"> <div class="name"> {currentEmployee.FirstName} {currentEmployee.LastName} </div> <div class="position"> {currentEmployee.Position} </div> </div> <span className={"dx-icon-" + data.icon + " dx-icon"}></span> </React.Fragment> ); }; export default function App() { return ( <DropDownButton icon="spindown" render={renderButton} /> ); } <template> <DxDropDownButton icon="spindown" template="button-template" > <template #button-template="{ data }"> <div class="text-container"> <div class="name"> {{ currentEmployee.FirstName }} {{ currentEmployee.LastName }} </div> <div class="position"> {{ currentEmployee.Position }} </div> </div> <span :class="'dx-icon-' + data.icon + ' dx-icon'"></span> </template> </DxDropDownButton> </template> $("#myDropDownButton").dxDropDownButton({ icon: 'spindown', template: (data, $element) => { const $textContainer = $('<div class="text-container">').appendTo($element); $(`<div class='name'>${currentEmployee.FirstName} {currentEmployee.LastName}</div>`).appendTo($textContainer); $(`<div class='position'> ${currentEmployee.Position} </div>`).appendTo($textContainer); $(`<span class="dx-icon-${data.icon} dx-icon"></span>`).appendTo($element); }, }); Select one of the following supported dev frameworks to explore the capabilities of this new feature: Angular | React | Vue | jQuery | ASP.NET Core | ASP.NET MVC #MENU/CONTEXTMENU — ITEM SCROLLING Submenus that exceed page size (in Menu or ContextMenu) can now be scrolled. You can use CSS stylesheets to customize submenus as needs dictate. For instance, the following code snippet restricts submenu height in ContextMenu: * CSS .dx-context-menu .dx-menu-items-container { max-height: 200px; } In the Menu component, use the onSubmenuShowing function to configure scroll-related settings. For instance, you can restrict the size of the submenu when item count surpasses a specified limit: * Angular * React * Vue * jQuery onSubmenuShowing({ submenuContainer, itemData } { if (itemData.items.length > 5) { submenuContainer.style.maxHeight = this.limitSubmenuHeight ? `200px` : ''; } } const onSubmenuShowing = useCallback(({ submenuContainer, itemData }) => { if (itemData.items.length > 5) { submenuContainer.style.maxHeight = limitSubmenuHeight ? `200px` : ''; } }, []); function onSubmenuShowing({ submenuContainer, itemData } { if (itemData.items.length > 5) { submenuContainer.style.maxHeight = limitSubmenuHeight.value ? '200px' : ''; } } onSubmenuShowing: ({ submenuContainer, itemData }) => { if (itemData.items.length > 5) { $(submenuContainer).css('maxHeight', 200 || ''); } } Select one of the following supported dev frameworks to explore the capabilities of this new feature: Menu: Angular | React | Vue | jQuery | ASP.NET Core | ASP.NET MVC ContextMenu: Angular | React | Vue | jQuery | ASP.NET Core | ASP.NET MVC #FORM — GROUP CAPTION CUSTOM CONTENT Our new Form groupItem.captionTemplate option enables custom content replacement for group captions. Select one of the following supported dev frameworks to explore the capabilities of this new feature: Angular | React | Vue | jQuery | ASP.NET Core | ASP.NET MVC #HTML EDITOR — SPELLCHECK AND CSP SUPPORT The DevExtreme HTML Editor now uses spellcheck functionality across all supported browsers. As you would expect, this addition enhances text editing capabilities through real-time spelling correction/suggestion support. Previous versions required Content Security Policy (CSP) directives when passing markup with inline styles to our HTML Editor. The DevExtreme HTML Editor v24.1 fully supports CSP. JS SCRIPT SIZE In our last major release cycle (v23.2), we reduced CSS size for built-in themes. In this release cycle, we reduced DevExtreme JS scripts size as follows: * We updated the ECMAScript compilation target for DevExtreme JS code. This eliminated the need for complicated syntactic constructions (due to transpiling) for operations supported by all modern browsers. * We ceased storage of time zone data. We switched to an internal browser time zone engine for time zone related operations. These modifications reduced bundle size by approximately 12%. ANGULAR 18 SUPPORT DevExtreme v24.1 supports Angular 18. Earlier versions (such as DevExtreme v23.2) are not compatible with Angular 18. Refer to the Angular Update Guide and our Migrate to the New Version help topic to update your application. NEW DXHTTPMODULE FOR ANGULAR #SIMPLIFIED REQUEST INTERCEPTION Angular HttpClientModule is a module that simplifies HTTP requests. It supports request and response interceptors, which allows you to introduce capabilities such as authentication tokens or logging across all HTTP requests. Previously, our DataSource, FileUploader, and Map components depended on non-native Angular Ajax requests for server communication. With v24.1, we transitioned these components from Ajax to the HttpClientModule. Simply import our DxHttpModule to activate this new functionality. In the following example, DataSource utilizes DxHttpModule for request interception. Online Demo SHADOW DOM SUPPORT (CTP) Shadow DOM represents one of three Web Components specifications, complemented by HTML templates and Custom Elements. Shadow DOM allows the attachment of a hidden, separate Document Object Model (DOM) to an element, termed the 'Shadow Host'. This hidden DOM, called the 'Shadow DOM', can contain additional nested Shadow Hosts, forming a structure known as a Shadow Tree. It's a direct method to create components with isolated CSS and JavaScript. Many everyday web interfaces use Shadow DOM (a feature available in all major browsers). This release cycle introduces Shadow DOM support in Angular, React, and Vue as a Community Technology Preview (CTP). Accordingly, you can now use DevExtreme components inside the Shadow DOM of custom HTML elements (Web Components). Note: CTPs includes limitations. Refer to our documentation for additional information: Angular | React | Vue Select one of the following supported dev frameworks to explore the capabilities of this new feature: Angular | React | Vue ACCESSIBILITY v24.1 accessibility-related enhancements include NVDA support for improved keyboard navigation and pronunciation support across the following components: * Tabs * TabPanel * TagBox * List * DropDownButton * Calendar * DataGrid with Master-Detail Additionally, DataGrid and TreeList now meet the Status Messages criterion. You can now access accessibility compliance (using the AXE® web accessibility evaluation tool) in the following DevExtreme demos: Data Grid Overview ASP.NET CORE - DATEONLY/TIMEONLY TYPE SUPPORT DevExtreme ASP.NET Core DataGrid now supports DateOnly and TimeOnly data types. DateOnly and TimeOnly data types offer the following benefits when compared to the traditional DateTime data type: * Usage clarity. * Improved database compatibility. * Less space during serialization. * Ability to mitigate potential errors/inconsistencies related to different time zones. The following DataGrid features support DateOnly and TimeOnly data types: * Filtering-related UI elements (filter row, filter panel, search panel, header filter) * Grouping (group interval data operations, both outside and inside a header filter) * Summary (min/max, count) * Razor <div id="grid"></div> <script> $(function() { $("#grid").dxDataGrid({ columns: [ { dataField: "orderDateOnly", dataType: "date", headerFilter: { groupInterval: "quarter" } }, { dataField: "orderTimeOnly", dataType: "time", },] }); }); </script> ASP.NET CORE - DATA VALIDATION #STANDALONE EDITOR VALIDATION With this release, you can use Razor syntax (in addition to Model-based method) to add validation rules directly to DevExtreme Editors. This method can be used in the following situations: * Modifying validation rules when model changes are impossible, such as when models are shared across views. * Adding extra editors to a view and defining associated validation rules independent of a model. * Razor @( Html.DevExtreme().TextBoxFor(m => m.StringProperty).ValidationRules(tvr => { tvr.AddRequired(); }) ) #REMOTE ATTRIBUTE — ADDITIONALFIELDS PROPERTY SUPPORT In ASP.NET Core, the Remote attribute facilitates client-side validation. Its AdditionalFields property enables server-based validation of field combinations. This release introduces support for the AdditionalFields option in the DevExtreme DataGrid and TreeList. The following code snippet validates email addresses in a DataGrid column. When a user enters an email that exists in the database, it determines whether to create a new profile or edit an existing record (refer to RemoteValidation Controller). To enable this validation, pass the ID field to AdditionalFields: * View * Model * Remote Validation Controller @(Html.DevExtreme().DataGrid<EmployeeValidation>() .Editing(editing => { editing.AllowUpdating(true); editing.AllowAdding(true); }) .Columns(columns => { columns.AddFor(m => m.ID); columns.AddFor(m => m.Email); }) ) using System.ComponentModel.DataAnnotations; public class EmployeeValidation { public int ID { get; set; } [Remote("CheckUniqueEmailAddress", "RemoteValidation", AdditionalFields = nameof(ID))] public string Email { get; set; } } [HttpPost] public JsonResult CheckUniqueEmailAddress(EmployeeValidation model) { var isValid = !db.Employees.Any(emp => { var equals = string.Equals(emp.Email, model.Email, StringComparison.OrdinalIgnoreCase); return model.ID != emp.ID && equals; }); return Json(isValid); } ASP.NET CORE - RICH TEXT EDITOR #NEW TABLE API With v24.1, the DevExpress Rich Text Editor for ASP.NET Core allows you to modify table layout, decoration, and structure at runtime. * JavaScript const columnCount = 5; const rowCount = 5; const table = richEdit.document.tables.create(0, columnCount, rowCount); table.autoFit = false; table.styleName = "Grid Table 5 Dark Accent 1"; table.width = { type: TableWidthType.Twips, value: 9000 }; table.tableStyleOptions = { ...table.tableStyleOptions, totalRow: true, headerRow: true, } for (let i = 0; i < table.rows.count; i++) { const cells = table.rows.getByIndex(i)!.cells; for (let j = 0; j < cells.count; j++) { const cell = cells.getByIndex(j)!; richEdit.document.insertText(cell.interval.start, `Row ${i} Cell ${j}`); } } #HTML EXPORT/IMPORT The Rich Text Editor now supports the import and export of documents in HTML format. You can add HTML markup to the main sub-document (insertHtml method overloads), obtain HTML text and markup of the main sub-document (getHtml method overloads), and download document content to a file in HTML format. SURVEY - JAVASCRIPT & ASP.NET CORE YOUR FEEDBACK MATTERS! Please login to complete the survey. SURVEY COMPLETED Thank you for taking the time to complete this survey. Your responses have now been posted. If you want to follow up with additional information, feel free to send us an email at clientservices@devexpress.com anytime. YOU'VE ALREADY COMPLETED THIS SURVEY Our records show that you have already completed this survey. If you want to follow up with additional information, send us an email at clientservices@devexpress.com. THIS SURVEY HAS EXPIRED If you want to share your feedback or request new functionality, please submit a new support ticket via the DevExpress Support Center. We’ll be happy to follow up. BLAZOR UI COMPONENTS V24.1 New TreeList (CTP) New HTML Editor New PDF Viewer (CTP) New Map New Polar Chart New Date Range Picker New DropDown Box New File Input New Drawer New Toast New Progress Bar New Bar Gauge New Sparkline New Rendering Engine Keyboard Support Project Templates Grid Charts New ComboBox and TagBox List Box Date Edit & Time Edit File Management Form Layout Rich Text Editor Scheduler Window and Popup Survey - Blazor Your feedback matters. Please, review the description of Blazor-related features below and leave your feedback at the end of the section. Go to the survey now. NEW TREELIST (CTP) Our new Blazor TreeList allows you to organize, display, and navigate hierarchical data with absolute ease. The component ships with the following integrated capabilities: * Data Sorting * Filter Row with Auto-Generated Editors * Total Summaries * Single and Multiple Node Selection * Focused Row * Header Bands * Paging and Scrolling * Virtual Scrolling * Toolbar * Keyboard Support Online Demo You will notice that the DevExpress Blazor TreeList and Grid UI components look and behave in a similar manner. This is not a coincidence. Our Blazor TreeList and Grid use the same rendering engine and rely upon common logic/algorithms. Thanks to commonalities between the components, we are in position to add new functionality to both of components simultaneously in future release cycles. #BIND TO FLAT DATA Our Blazor TreeList component can be bound to any traditional data source. Since the TreeList is designed to display information using a tree structure, its data source must meet specific requirements. If a data source contains flat data, two additional fields are necessary to build the appropriate tree structure: * A field that contains a node’s unique identifier. Assign this field to the KeyFieldName property. * A field that contains the unique identifier of a node’s parent. Assign this field to the ParentKeyFieldName property. The following example binds the Blazor TreeList component to a flat data source: * Razor @inject IEmployeeTaskDataProvider EmployeeTaskDataProvider <DxTreeList Data="@TreeListData" KeyFieldName="Id" ParentKeyFieldName="ParentId"> <Columns> <DxTreeListDataColumn FieldName="Name" /> <DxTreeListDataColumn FieldName="EmployeeName"/> <DxTreeListDataColumn FieldName="StartDate" /> <DxTreeListDataColumn FieldName="DueDate" /> </Columns> </DxTreeList> @code { List<EmployeeTask> TreeListData { get; set; } protected override void OnInitialized () { TreeListData = EmployeeTaskDataProvider.GenerateData(); } } #BIND TO SERVER-SIDE DATA You can also bind the DevExpress Blazor TreeList component to our DevExtremeDataSource. This data source allows you to improve TreeList performance when binding large data sets for the following reasons: * The TreeList loads child nodes on demand (when user expands a node). * DevExtremeDataSource performs data filtering operations on the server. To bind the component to DevExtremeDataSource, you must: * Assign a GridDevExtremeDataSource instance to the Data property * Specify KeyFieldName and ParentKeyFieldName properties. * Specify the HasChildrenFieldName property. This property helps determine whether a node includes children and if the node requires an expand button. #BIND TO HIERARCHICAL DATA If each node in your data source includes a field with a list of child nodes, assign the field’s name to the ChildrenFieldName property and bind the Data property to the data source: * Razor @inject ISpaceObjectDataProvider SpaceObjectDataProvider <DxTreeList Data="@TreeListData" ChildrenFieldName="Satellites"> <Columns> <DxTreeListDataColumn FieldName="Name"/> <DxTreeListDataColumn FieldName="TypeOfObject" Caption="Type"/> <DxTreeListDataColumn FieldName="Mass" Caption="Mass, kg"/> <DxTreeListDataColumn FieldName="MeanRadius" Caption="Radius, km"/> </Columns> </DxTreeList> @code { List<SpaceObject> TreeListData { get; set; } protected override void OnInitialized () { TreeListData = SpaceObjectDataProvider.GenerateData(); } } Alternatively, you can assign a collection of root nodes to the Data property and handle the ChildrenLoading event to populate nodes with children. In the event handler, use the Parent argument to determine the processed node and assign this node’s children to the Children property. #LOAD DATA ON DEMAND The DevExpress Blazor TreeList allows you to initially load only root nodes and retrieve node children when a node is expanded for the first time. To switch the component to on demand mode, follow the steps below: * Assign root data items to the Data property. * Specify the HasChildrenFieldName property. * Handle the ChildrenLoadingOnDemand event. In the event handler, use the Parent argument to determine the processed node and assign the node’s children to the Children event argument. The following example loads TreeList data on demand: * Razor @inject FileSystemDataProvider FileSystemDataProvider <DxTreeList Data="TreeListData" HasChildrenFieldName="HasChildren" ChildrenLoadingOnDemand="TreeList_ChildrenLoadingOnDemand"> <Columns> <DxTreeListDataColumn FieldName="Name" /> <DxTreeListDataColumn FieldName="Type" /> <DxTreeListDataColumn FieldName="DateModified" /> <DxTreeListDataColumn FieldName="Size" /> </Columns> </DxTreeList> @code { object TreeListData { get; set; } protected override async Task OnInitializedAsync() { Data = await FileSystemDataProvider.GetRootItemsAsync(); } Task TreeList_ChildrenLoadingOnDemand(TreeListChildrenLoadingOnDemandEventArgs e) { var item = e.Parent as FileSystemDataItem; e.Children = item.Children; return Task.CompletedTask; } } NEW HTML EDITOR Our Blazor HTML Editor allows you to format/display text and visual content and store it as HTML or Markdown. Users can apply inline formatting and modify font, size, and color as needs dictate. Additionally, the DevExpress Blazor HTML Editor offers the following integrated features: * Block formatting, including headings, text alignment, lists (bullet and numbered), code blocks, and quotes. * Variables support (for example, {{companyName}}): Among other use cases, this capability can be used to generate dynamic email content. * Toolbar with adaptive layout support. * Built-in toolbar customization. * Image Insert: You can upload an image from the local file system or specify a URL. * Table support. * Mentions support. Online Demo NEW PDF VIEWER (CTP) The new DevExpress Blazor PDF Viewer component can display PDF file content directly in your DevExpress-powered Blazor app. The component allows you to navigate through the document, set zoom level, print, and download the document. Additionally, the CTP version of the Blazor PDF Viewer includes a single-page preview and toolbar customization option (such as rearranging, grouping, hiding, and adding items) Online Demo NEW MAP The DevExpress Blazor Map component can display geo maps with markers and route info within your DevExpress-powered Blazor web app. The component retrieves relevant data from a GIS service (Bing, Google, or GoogleStatic - requires application authentication with an appropriate API key) and ships with the following capabilities: * Marker/route configuration and customization options. * Built-in map navigation and type controls. * Manual map adjustment (set Zoom and MapCenter). * Map and marker "click" support. Online Demo NEW POLAR CHART The DevExpress Polar Chart for Blazor allows you to visualize data within a polar coordinate system - where each point on a plane is determined by the distance from the center and the angle from a fixed direction. The DevExpress Blazor Polar Chart component ships with the following capabilities: * Multiple series types: line, area, bar, stacked bar, and scatter. * Continuous, discrete, and logarithmic axis value support. * Spider web mode. * Chart element customization: labels, tooltips, legend, and many more. Online Demo NEW DATE RANGE PICKER The DevExpress Date Range Picker for Blazor allows you to select a range of dates within a single calendar dropdown. The component ships with the following integrated capabilities: * Minimum and maximum dates * Special date highlighting * Selected date formatting API * Input validation * Clear button * Nullable date support and placeholder * Automatic support for browser time zone and localization Online Demo NEW DROPDOWN BOX The DevExpress Blazor DropDown Box is a customizable editor - designed to display/use a variety of UI elements within its drop-down window: from simple lists and trees, to grids, or any combination therein. You can assign an editor value programmatically based on page interactions. The following code snippet adds the DevExpress Blazor Grid to the DropDown Box popup. * Razor <DxDropDownBox Value="Value" QueryDisplayText="QueryText"> <DropDownBodyTemplate> <DxGrid Data="@GridData" ShowSearchBox="true" SelectedDataItem="@Value" SelectedDataItemChanged="item => GridSelectedDataItemChanged(item, context.DropDownBox)" .../> </DropDownBodyTemplate> </DxDropDownBox> @code { Customer Value { get; set; } IEnumerable<object> GridData { get; set; } string QueryText(DropDownBoxQueryDisplayTextContext arg) { if(arg.Value is Customer value) return value.ContactName; return string.Empty; } void GridSelectedDataItemChanged(object item, IDropDownBox dropDownBox) { Value = item as Customer; dropDownBox.HideDropDown(); } } The DropDown Box' value is not limited to a single object. It can be a collection of objects (for those looking to implement a multi-selection editor): Or even a composite data item generated based on user selection made within the popup: Online Demo NEW FILE INPUT Our new Blazor File Input component allows you to introduce file upload functionality to your Blazor app without creating a separate Web API project with an upload controller. Our Blazor File Input control supports multiple upload modes (Instant and OnButtonClick), can upload multiple files simultaneously, and allows you to validate file size and extension both on the client and server. Handle the FilesUploading event to upload selected files. For each file, the event supplies a Stream you can open to read file content. Once the read operation is complete, you can send the file to another destination, save it to the file system, or display the file content on a web page. The following code snippet configures FileInput to upload files to a specified folder: * Razor <DxFileInput FilesUploading="OnFilesUploading" /> @code { async Task OnFilesUploading(FilesUploadingEventArgs args) { foreach (var file in args.Files) { Stream? stream = default; var filePath = "full path to the uploaded file"; FileStream fs = new(filePath, FileMode.Create); try { if(IsValidFile(file)) { stream = file.OpenReadStream(int.MaxValue); await stream.CopyToAsync(fs); } } catch (Exception ex) { if (file.CancellationTokenSource.IsCancellationRequested) // Handle the cancel action here } finally { await fs.FlushAsync(); fs.Close(); if (stream != null) stream.Close(); } } } } Note: Before adding file upload capabilities to your Blazor app, make certain to institute necessary security-related processes (to avoid risks and control unauthorized file operations). Online Demo NEW DRAWER Our new Blazor Drawer component allows you to add a "dismissible" navigation side panel to your web application. The control includes the following features: * Left-side and right-side position. * Overlap and shrink display modes. * The minimized drawer state. * Header, body, and footer templates. Online Demo NEW TOAST Our new Blazor Toast component allows you to notify users about processes and events. Notification messages can remain visible until a user clicks the close button or closed automatically after a predetermined amount of time. The DevExpress Blazor Toast component supports four theme modes (Dark, Light, Pastel, and Saturated) and the following notification styles: * Danger * Info * Primary * Success * Warning You can place a DxToast component in markup and call the Show method to display it. * Razor <DxToastProvider Name="ToastContainer" /> <DxToast @ref=toast Text="The process has been completed." ProviderName="ToastContainer" /> @code { DxToast toast; protected override void OnAfterRender(bool firstRender) { toast.Show(); } } </lang> </code2> <para> Alternatively, use the notification service to create toasts at runtime. </para> <code2> <lang brush="razor" name="Razor"> <DxToastProvider Name="ToastContainer" /> @code { [Inject] IToastNotificationService ToastService { get; set; } protected override void OnAfterRender(bool firstRender) { ToastService.ShowToast(new ToastOptions { ProviderName = "ToastContainer", Text = "The process has been completed." }); } } In both instances, you must add the DxToastProvider component to a page. This component serves as a toast container and should be declared where toasts will be displayed. Online Demo NEW PROGRESS BAR The new DevExpress Blazor Progress Bar component allows you to communicate the status of ongoing processes with end-users. When progress cannot be estimated, the component can display an infinite moving bar. The control includes the following integrated features: * Horizontal, vertical, and circular layout * Four statuses to indicate process state: InProgress, Warning, Error, and Success * Indeterminate state * Element customization: icon, label, and bar thickness Online Demo NEW BAR GAUGE The Bar Gauge for Blazor allows you to display data as circular bars where each bar indicates a single value. The component ships with the following capabilities: * Geometry and layout configuration * Palette customization * Export and printing support * Real-time data updates * Gauge element customization: labels, tooltips, legend, and many more. Online Demo NEW SPARKLINE Our new Blazor Sparkline component allows you to display value trends using a compact UI metaphor. You can use the DevExpress Blazor Sparkline as a standalone component or embed it into other UI controls. Sparkline allows you to configure all series and point settings at the root component level. Sparkline applies corresponding settings based on the Type property value (which defines series type). In addition to series and point settings, you can configure tooltips and customize the component's container. Sparkline includes built-in export and print capabilities. You can call the ExportToAsync method to export data to a file (PNG, PDF, JPEG, or SVG) or call the GetSvgMarkup method to obtain the component's SVG markup. Online Demo NEW RENDERING ENGINE The following DevExpress Blazor components now use our optimized rendering engine (instead of Bootstrap): * Charts * Rich Text Editor * Scheduler * Pivot Grid * Upload * Report Viewer KEYBOARD SUPPORT To address accessibility standards and improve user experiences for those with disabilities, v24.1 adds keyboard navigation support for the following Blazor UI components: * Date Edit * Time Edit * Tree View * Accordion * ComboBox * List Box * TagBox * Rich Text Editor * Upload * Report Viewer PROJECT TEMPLATES #.NET 8 AUTHENTICATION AND AUTHORIZATION Our Blazor project templates for .NET 8 include an option to add ASP.NET Core Identity and Token-based Authentication to your projects. In addition to the necessary infrastructure, our templates generate an authentication interface powered by DevExpress Blazor components. GRID #HEADER BANDS The DevExpress Blazor Grid can now arrange its columns into logical groups called bands. Each band contains its own header displayed above column headers. Columns without a band span the entire band region. The Grid also supports multi-level bands wherein a band can display other bands within it. Documentation While end-users can reorder columns within bands or move them to the Group Panel, column movement between bands is restricted. The Grid’s Column Chooser has also been updated to support Header Bands. It displays bands and columns hierarchically and allows end-users to toggle the visibility of entire groups, not just individual columns. Online Demo #EXPORT SERVER-SIDE DATA v24.1 introduces Blazor Grid data export functionality for any supported server-side data/Server Mode sources (GridDevExtremeDataSource, or CustomDataSource). Remote data can be exported to XLS, XLSX, and CSV formats. The DevExpress Blazor Grid can now fetch records from a remote data source to/from the exported document. While fetching records, the Grid displays a loading indicator. To avoid flickering, the indicator is displayed only during estimated fetch time. For more information on this feature, refer to the following help topic: Data Export. Online Demo #NEW CELL EDITOR APPEARANCE In-place editors in the filter row, edit row, and edit cells of the DevExpress Blazor Grid ship with a new improved look/feel - and automatically display validation icons, when required. The appearance of grid cells is now consistent in both display and edit modes. v23.2v24.1 Online Demo #CELL EDITING ENHANCEMENTS Our Blazor Grid's Edit Cell mode feature is now official and includes Virtual Scrolling support. It now ships with the following enhancements: * Users can now change a check box value with a single click. * The Grid automatically selects cell text when the cell switches to edit mode. * The Grid now automatically updates the focused row when switching to edit mode. * The Grid’s new GetEditContext method allows you to obtain edit context at any time. * Column text alignment affects editors displayed inside the column. #KEYBOARD NAVIGATION ENHANCEMENTS AND NEW TAB NAVIGATION In v24.1, our Blazor Grid ships with enhanced keyboard navigation and virtual scrolling support. The Grid component now automatically activates keyboard navigation and built-in shortcuts (Note: You may want to remove the KeyboardNavigationEnabled property from your project as it's now obsolete). The Tab key navigates between all Grid cells regardless of a cell editor's active state. Users can also leave the table area by pressing Ctrl + Up or Ctrl + Down (Alt + Up or Alt + Down on Mac). In addition, we improved the RowClick event. With v24.1, this event allows you to implement custom actions in response to mouse clicks and after a user presses Enter when a data row has focus. #BUILT-IN VALUE POSTING We added the following new method to EditModelSaving event arguments: CopyChangesToDataItem. This method allows you to copy all changes made to the edit model during editing. Complex field values can be copied as well. The following v23.2 code snippet... * C# async Task OnEditModelSaving(GridEditModelSavingEventArgs e) { var editModel = (EmployeeEditModel)e.EditModel; if (dataItem != null) { dataItem.FirstName = editModel.FirstName; dataItem.LastName = editModel.LastName; dataItem.Title = editModel.Title; dataItem.HireDate = editModel.HireDate; } } ... can now be replaced with a shorter version: * C# async Task OnEditModelSaving(GridEditModelSavingEventArgs e) { var editModel = (EmployeeEditModel)e.EditModel; if (dataItem != null) { e.CopyChangesToDataItem(); } } #DATEONLY AND TIMEONLY SUPPORT With v24.1, our Blazor Grid component supports DateOnly and TimeOnly types for the following: * Sorting * Filtering * Hierarchical Filter Menu for DateOnly values * Grouping * Summaries * Auto-generated cell editors * Interval grouping for DateOnly values * Value formatting using DisplayFormat * Excel Export #ENABLE/DISABLE SKELETONS The DevExpress Blazor Grid no longer displays skeletons by default when Virtual Scrolling is used with local data. Since rows in a local data source are usually rendered quickly, this new behavior produces a more fluid experience, with fewer visual updates. Skeletons are still enabled by default for remote data sources (for record loading from a server or database). You can now use the SkeletonRowsEnabled property to control skeleton behavior - enable it for local sources or disable it for remote sources if server response time is acceptable. #HIGHLIGHT ROWS ON HOVER To highlight Blazor Grid rows when hovering rows, simply enable our new HighlightRowOnHover property (highlight color is based on the theme used within your DevExpress-powered Blazor app). CHARTS #ANNOTATIONS The new Blazor DxChartAnnotation object allows you to create chart annotations — comments that contain information about chart content. You can populate annotations with image or text content. You can also anchor annotations to chart elements (series points or axes) or position annotations based on pixel coordinates. DevExpress Blazor Chart components also allow you to customize annotations as needed — you can configure annotation borders and shadows, image and text settings. Online Demo #STRIPS Our new Blazor DxChartAxisStrip object allows you to create and configure axis strips. You can use a strip to highlight a range between two axis values or an area above/below a value. These highlighted areas help users determine whether a point falls in or out of a predefined range. You can also add a DxChartAxisStripLabel object to strip markup to display and configure strip labels. Online Demo #ERROR BARS The new DxChartSeriesValueErrorBar object allows you to configure error bars (indicate measurement precision or uncertainty). They display a possible value range next to a series point. Error bars can display fixed values or percentages, statistical function values, or error values obtained from data source fields. Online Demo #TOOLTIP ENHANCEMENTS v24.1 introduces extended tooltip functionality for DevExpress Blazor Chart components. You can now change tooltip visibility for individual series points in code. To display a tooltip for a particular series point, call component-specific ShowTooltip method overloads (DxChart.ShowTooltip, DxPieChart.ShowTooltip, or DxPolarChart.ShowTooltip). To hide the tooltip, call the HideTooltip method. With v24.1, you can also handle the TooltipShowing event to obtain information about a tooltip before it appears (or cancel the tooltip as needed). #LABEL CUSTOMIZATION ENHANCEMENTS We expanded the list of available label customization settings. You can now set individual text for each point label using the Texts property. Moreover, you can modify the following properties for point labels: * Alignment * HorizontalOffset * VerticalOffset * RotationAngle * ShowForZeroValues * Font * Border #LIVE UPDATE ENHANCEMENTS We extended our Blazor Chart’s live update capabilities and introduced Length and VisualRangeUpdateMode properties. These enhancements allow the chart to retain its visual state (zoom and scroll position) when Chart data changes. Online Demo #API ENHANCEMENTS PieChart settings: * SegmentDirection - Specifies the direction in which the chart arranges series slices. * StartAngle - Specifies the angle at which the chart positions the first series slice. Axis settings: * WorkdaysOnly - Specifies whether the chart displays only workdays on the axis. * WorkWeek - Specifies weekdays DxChart treats as workdays. * WorkDates - Specifies dates DxChart treats as workdays. * Holidays - Specifies dates DxChart marks as holidays. Axis Range settings: * Length - Specifies range length. * MinVisualRangeLength - Specifies the minimum length of the visual range. * VisualRangeUpdateMode - Specifies how the visual range behaves if new points are added to the data source. NEW COMBOBOX AND TAGBOX We've rebuilt the DevExpress Blazor ComboBox and TagBox components, maintaining their existing API while revamping visual and data layers for improved stability, visuals, and performance. These changes form the basis for upcoming features and enhancements, with many already available in v24.1. Online Demo: ComboBoxOnline Demo: TagBox #PERFORMANCE ENHANCEMENTS Overall ComboBox and TagBox performance has been improved significantly. Tasks like opening the dropdown, searching, or navigating through items are now more responsive. In addition, startup times for ComboBox/TagBox have been reduced by up to three times. This boosts overall performance for forms that contain these editors and any components utilizing ComboBox/TagBox internally, such as our Blazor Grid, Rich Text Editor, Scheduler, and Toolbar. #SEARCH ACROSS MULTIPLE COLUMNS Based on customer feedback, our ComboBox and TagBox can now search for text in any defined column, even columns whose values are not displayed in the edit box. Use the new SearchEnabled property to exclude specific columns from search when necessary. #NEW SEARCH API In addition to `Contains` and `StartsWith`, ComboBox and TagBox include an `Equals` condition for searching within collections of similarly named items. The new SearchTextParseMode property also defines how editors interpret search strings divided by spaces: * GroupWordsByAnd – search words are treated as individual conditions grouped by the AND logical operator; only items that match all of the words are displayed. * GroupWordsByOr – search words are treated as individual conditions grouped by the OR logical operator; items that match at least one of these words are displayed. * ExactMatch – search words are not treated separately; only items that match search text (exact match) are displayed. #NEW TEMPLATES We've introduced new templates for ComboBox and TagBox to simplify popular customization usage scenarios: * ColumnCellDisplayTemplate – allows you to implement custom formatting for values in a multi-column ComboBox/TagBox. * ItemDisplayTemplate/TagDisplayTemplate – these templates are similar to ItemTemplate/TagTemplate (available previously), but offer information about the underlying data item, value, and displayed text in context. * EmptyDataAreaTemplate – allows you to customize the area displayed when the ComboBox/TagBox popup displays no items. #KEYBOARD NAVIGATION ENHANCEMENTS Both ComboBox and TagBox now use a client-side keyboard navigation engine in their dropdowns. This makes keyboard navigation more responsive in Blazor Server apps since each keystroke doesn’t need to be sent to the server. In addition, keyboard navigation is now more stable when used in combination with Virtual Scrolling. LIST BOX #NEW SEARCH AND FILTER API The DevExpress Blazor List Box introduces new API that allows you to connect it to external search/filter UI elements: * SearchText – specifies text used by the List Box to filter and highlight search results. * SearchTextParseMode – specifies how the List Box interprets search strings divided by spaces. * SetFilterCriteria/GetFilterCriteria/ClearFilter – allows you to apply filters (of any complexity) using the CriteriaOperator language. Documentation Online Demo #NEW SCROLL API The following new APIs allow you to scroll to a specific ListBox item: * MakeItemVisible – scrolls to an item with a specified visible index. * MakeDataItemVisibleAsync – finds a data item in the list and scrolls to it. DATE EDIT & TIME EDIT #DATEONLY AND TIMEONLY SUPPORT DevExpress Blazor Date Edit and Time Edit components now support DateOnly and TimeOnly values, respectively. All editor features - including masks, formatting API, and validation - now function properly with these new data types. FILE MANAGEMENT #NEW UPLOAD APPEARANCE Our Blazor Upload component's file list ships with a revamped look and feel. To make the list more understandable and visually compact, we removed the common progress bar, resized and rearranged UI elements, updated icons, and added text to certain action buttons. v23.2v24.1 Online Demo FORM LAYOUT #ITEM CAPTION TEMPLATE The new DxFormLayoutItem.CaptionTemplate property allows you to set icons, buttons, links, or other elements near each LayoutItem caption. * Razor <DxFormLayoutItem> <CaptionTemplate> <div class="email-caption"> <label for="contactEmail">Email</label> <DxButton CssClass="info-icon-btn" IconCssClass="info-icon text-info" RenderStyle="@ButtonRenderStyle.None" Click="() => IsInfoOpen = !IsInfoOpen" /> <DxFlyout @bind-IsOpen=@IsInfoOpen PositionTarget=".info-icon-btn" PreventCloseOnPositionTargetClick="true" Width="240"> Email must contain the company's domain name. </DxFlyout> </div> </CaptionTemplate> <Template> <DxTextBox @bind-Text="@Email" InputId="contactEmail"/> </Template> </DxFormLayoutItem> Online Demo RICH TEXT EDITOR #NEW TABLE API With v24.1, the DevExpress Rich Text Editor for Blazor allows you to modify table layout, decoration, and structure at runtime. Documentation * Razor <DxRichEdit @ref="@richEdit" /> @code { DxRichEdit richEdit { get; set; } @* ... *@ try { @* ... *@ var columnCount = 4; var rowCount = 5; richEdit.DocumentAPI.BeginUpdate(); await richEdit.DocumentAPI.Tables.CreateAsync(0, columnCount, rowCount); for (int i = 0; i < rowCount; i++) for (int j = 0; j < columnCount; j++) { var myTable = await richEdit.DocumentAPI.Tables.GetAsync(0); var cellPosition = myTable.Rows[i].Cells[j].Interval.Start; await richEdit.DocumentAPI.AddTextAsync(cellPosition, "Row=" + (i + 1) + ",Column=" + (j + 1)); } richEdit.DocumentAPI.EndUpdate(); @* ... *@ } catch (OperationCanceledException e) { @* ... *@ } } #HTML EXPORT/IMPORT The DevExpress Rich Text Editor for Blazor now supports document import/export in HTML format. You can add HTML markup to the main sub-document (AddHtmlAsync method overloads), obtain HTML text and markup of the main sub-document (GetHtmlAsync method overloads), and download document content to a file in HTML format. Online Demo #CONTEXT MENU CUSTOMIZATION v24.1 introduces extended UI customization options for the DevExpress Blazor Rich Text Editor. You can now customize the component's context menu and associated sub-menus. Handle the CustomizeContextMenu event to: * Add or remove built-in menu items * Add custom menu items * Customize item appearance/behavior. With v24.1, you can also control context menu visibility using the ContextMenuEnabled property. * Razor <DxRichEdit CustomizeContextMenu=OnCustomizeContextMenu /> @code { void OnCustomizeContextMenu(IContextMenuItemCollection items) { if (selection.Intervals[0].Length > 0) { var span = await selection.ActiveSubDocument.GetTextSpanAsync(selection.Intervals[0]); textToSearch = span.Text.Trim(); } else textToSearch = null; var searchItem = items.AddCustomItem(0, "Google Search...", async () => { var url = String.Format("https://www.google.com/search?q={0}", HttpUtility.UrlEncode(textToSearch)); await JSRuntime.InvokeVoidAsync("open", url, "_blank"); }); searchItem.Enabled = !string.IsNullOrEmpty(textToSearch); searchItem.IconCssClass = "search-icon"; items.Remove(RichEditContextMenuItemNames.CutSelection); items.Remove(RichEditContextMenuItemNames.CopySelection); items.Remove(RichEditContextMenuItemNames.Paste); var clipboardItem = items.AddCustomItem(1, "Clipboard"); clipboardItem.BeginGroup = true; clipboardItem.Items.Add(RichEditContextMenuItemNames.CutSelection); clipboardItem.Items.Add(RichEditContextMenuItemNames.CopySelection); clipboardItem.Items.Add(RichEditContextMenuItemNames.Paste); } } SCHEDULER #MULTIPLE RESOURCES Our Blazor Scheduler allows users to assign multiple resources to an appointment. With v24,1, users can create meetings with multiple participants, group events, or services that require coordination among multiple resources. To enable this functionality, use the EnableMultipleResources property. Once enabled, appointment forms will allow multiple selection in the Resource field: All selected resources will be displayed in the appointment tooltip: If the Scheduler is grouped by resources, multi-resource appointments will appear under all selected resources. Online Demo #BUILT-IN SCROLL BARS The DevExpress Blazor Scheduler component now automatically displays a scroll bar when cells don't fit within control boundaries/size. To specify Scheduler boundaries/size, modify width/height parameters using CSS: * Razor <style> .my-scheduler { height: 600px; } </style> <DxScheduler ... CssClass="my-scheduler"/> #SCROLL API v24.1 ships with a new ScrollTo() method. This method scrolls the view area to a specified date or appointment. When used, ScrollTo() can help you focus user attention on the most important time/appointment/event within the currently displayed view (for example, the beginning of a work day). * Razor <DxScheduler ... @ref="Scheduler" /> @code { DxScheduler Scheduler { get; set; } DesiredDate = new DateTime(2024, 05, 14) // ... protected override void OnAfterRender(bool firstRender) { base.OnAfterRender(firstRender); if (firstRender) { Scheduler.ScrollTo(DesiredDate); } } } #RECURRENCE FORM CUSTOMIZATION We enhanced the Scheduler's AppointmentFormShowing event. It now allows you to customize recurrence options for both Appointment and Recurrence forms. For instance, you can modify the list of items available in the Appointment form’s Repeat section as needs dictate: ...Or modify the list of repeat end items and weekday list in the Recurrence form: The following code snippet customizes the Scheduler's recurrence options: * Razor <DxScheduler ... AppointmentFormShowing="OnAppointmentFormShowing"/> void OnAppointmentFormShowing(SchedulerAppointmentFormEventArgs args) { args.FormInfo.RepeatItems = new List<SchedulerRecurrenceType>() { SchedulerRecurrenceType.Yearly, SchedulerRecurrenceType.Weekly, SchedulerRecurrenceType.Never }; args.FormInfo.RecurrenceFormInfo.RepeatEndItems = new List<SchedulerRecurrenceRange>() { SchedulerRecurrenceRange.OccurrenceCount, SchedulerRecurrenceRange.EndByDate }; args.FormInfo.RecurrenceFormInfo.WeekDayItems.Remove(SchedulerWeekDays.WeekendDays); } } #DAY, WEEK, WORKWEEK VIEWS – MINIMUM CELL WIDTH You can now specify the minimum width of a day cell in day, week, and work week views. Pass the integer value to the CellMinWidth property to set this width in pixels. WINDOW AND POPUP #DRAG AND DROP USING MULTIPLE WINDOW ELEMENTS Disable the new DxPopup.AllowDragByHeaderOnly / DxWindow.AllowDragByHeaderOnly option to allow users to drag and drop a window by its header, body, or footer. Online Demo: WindowOnline Demo: Popup SURVEY - BLAZOR YOUR FEEDBACK MATTERS! Please login to complete the survey. SURVEY COMPLETED Thank you for taking the time to complete this survey. Your responses have now been posted. If you want to follow up with additional information, feel free to send us an email at clientservices@devexpress.com anytime. YOU'VE ALREADY COMPLETED THIS SURVEY Our records show that you have already completed this survey. If you want to follow up with additional information, send us an email at clientservices@devexpress.com. THIS SURVEY HAS EXPIRED If you want to share your feedback or request new functionality, please submit a new support ticket via the DevExpress Support Center. We’ll be happy to follow up. .NET REPORTING V24.1 Reporting for Web Reporting for Blazor All Platforms Cloud Deployment Accessibility Data Sources Survey - Reporting Your feedback matters. Please, review the description of DevExpress Reporting-related features below and leave your feedback at the end of the section. Go to the survey now. REPORTING FOR WEB #NATIVE REACT REPORT VIEWER COMPONENT Our native React Report Viewer component leverages the internal architecture of the DevExpress Angular Report Viewer and associated assistive technologies. Our implementation delivers superior user experiences and improved performance when compared to solutions based on JavaScript wrappers. Our new React Report Viewer ships with the following built-in customization capabilities: Toolbar Customization * JavaScript 'use client'; import React from 'react'; import ReportViewer, { Callbacks, RequestSettings } from 'devexpress-reporting-react/dx-report-viewer'; import { TemplateEngine } from 'devexpress-reporting-react/dx-report-viewer/core/template-engine'; import { ActionId } from 'devexpress-reporting/viewer/constants'; import { CustomAction } from 'devexpress-reporting/dx-webdocumentviewer'; import "devextreme/dist/css/dx.light.css"; import "@devexpress/analytics-core/dist/css/dx-analytics.common.css"; import "@devexpress/analytics-core/dist/css/dx-analytics.light.css"; import "devexpress-reporting/dist/css/dx-webdocumentviewer.css"; import styles from "./page.module.css"; export default function Home() { <!--don't remove this line/comment--> const templateEngine = new TemplateEngine(); templateEngine.setTemplate('slideshow', () => ( <svg version="1.1" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" viewBox="0 0 24 24"> <polygon className="dxd-icon-fill" points="4,2 4,22 22,12 " /> </svg> )); const handleCustomizeMenuActions = ({ sender, args }: { sender: any, args: any }) => { let interval: any; const action = new CustomAction({ text: "Run Slide Show", imageTemplateName: "slideshow", visible: true, disabled: false, selected: false, clickAction: function () { if (this.selected) { clearInterval(interval); this.selected = false; return; } var model = sender.GetPreviewModel(); if (model) { this.selected = true; interval = setInterval(function () { var pageIndex = model.GetCurrentPageIndex(); model.GoToPage(pageIndex + 1); }, 2000); } } }); args.Actions.push(action); var highlightEditingFieldsAction = args.GetById(ActionId.HighlightEditingFields); if (highlightEditingFieldsAction) highlightEditingFieldsAction.visible = false; }; return ( <main className={styles.main}> <ReportViewer reportUrl="Report" templateEngine={templateEngine}> <RequestSettings invokeAction="/DXXRDV" host="http://localhost:5065" /> <Callbacks CustomizeMenuActions={React.useCallback(handleCustomizeMenuActions,[])} /> </ReportViewer> </main> ); } Example: Reporting for React - Customize Viewer Toolbar Parameters Customization The following sample code declares a custom template for the Parameter Editor and applies validation rules to the NumberBox component (used to edit the "Age" report parameter value): * JavaScript const CustomizeParameterEditor = ({data}: {data: IEditorViewModel}) => ( <NumberBox showSpinButtons={true} value={data.value} disabled={data.disabled}> <Validator validationRules={data.validationRules}> </Validator> </NumberBox> ); export default function Home() { const templateEngine = new TemplateEngine(); templateEngine.setTemplate('custom-parameter-editor', CustomizeParameterEditor); const handleCustomizeParameterEditors = React.useCallback((event: any): void => { const parameter = event.args.parameter; const info = event.args.info; const curYear = new Date().getFullYear(); if (parameter.type === 'CustomParameterType') { info.validationRules = info.validationRules || []; info.validationRules.push({ type: 'range', min: 1900, max: curYear, message: `The Birth Year parameter value should be in a range from 1900 to ${curYear}.` }); info.editor.header = "custom-parameter-editor"; } }, []); return ( <main className={styles.main}> <ReportViewer reportUrl="CustomParameterReport" templateEngine={templateEngine}> <RequestSettings invokeAction="/DXXRDV" host="http://localhost:2119/" /> <Callbacks CustomizeParameterEditors={handleCustomizeParameterEditors} /> </ReportViewer> </main> ); } Documentation: Create a React Application with Web Document Viewer (Next.js) #NATIVE ANGULAR REPORT VIEWER Toolbar Customization API With this release, our Angular Report Viewer allows you to customize its built-in toolbar as requirements dictate. The following code snippet hides a toolbar item using the CustomizeMenuActions event handler: * CustomizeMenuActions(event) { var actionSearch = event.args.GetById(ActionId.Search); if (actionSearch) actionSearch.visible = false; } var highlightEditingFieldsAction = e.GetById(DevExpress.Reporting.Viewer.ActionId.HighlightEditingFields); if (highlightEditingFieldsAction) highlightEditingFieldsAction.visible = false; } The following code snippet adds a custom export option to the toolbar using the same event handler: * function CustomizeMenuActions(event) { const actionExportTo = event.args.GetById(ActionId.ExportTo); const newFormat = { format: 'NewFormat', text: 'New Format' }; if (actionExportTo) { actionExportTo.events.on('propertyChanged', (args) => { const formats = actionExportTo.items[0].items; if (args.propertyName === 'items' && formats.indexOf(newFormat) === -1) { formats.push(newFormat); } }); } } OnPush Change Detection Strategy Support v24.1 also adds support for OnPush Change Detection Strategy. Angular's OnPush change detection strategy improves performance by reducing unnecessary rendering cycles and only triggering change detection when input references change. With this update, you can change the detection strategy from default to ChangeDetectionStrategy.OnPush by adding the changeDetection property in the @Component decorator as follows: * import { Component, ViewEncapsulation } from '@angular/core'; import { CommonModule } from '@angular/common'; import { RouterOutlet } from '@angular/router'; import { DxReportViewerModule } from 'devexpress-reporting-angular'; @Component ({ selector: 'app-root', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, standalone: true, imports: [ CommonModule, RouterOutlet, DxReportViewerModule ], templateUrl: './app.component.html', styleUrls: [...] }) export class AppComponent { title = 'DXReportViewerSample'; reportUrl: string = 'TestReport'; hostUrl: string = 'https://localhost:5001/'; invokeAction: string = '/DXXRDV'; } #NEW STANDALONE PARAMETERS PANEL COMPONENT FOR ASP.NET CORE, BLAZOR, ANGULAR Our new Report Parameters Panel component automatically generates a layout for report parameter editors (including associated grouping) based on a report instance supplied from the backend. This component addresses a variety of usage scenarios, including the need to programmatically create a report and export it or send it by mail - without displaying its print preview to an end-user. Our Standalone Parameters Panel helps reduce an app’s overall memory footprint because it eliminates the need to generate report images in the background and send them to a client app. Component implementation is based on the Parameters Panel in our Report Viewer component. As such, it gives you access to the same set of component public properties and events related to report parameters. Here's a sample component definition for the Angular platform: * <dx-report-parameters-panel class="parametersPanel" [reportUrl]="yourReportName" height="560px" width="400px"> <dxrpp-request-options [invokeAction]="invokeAction" host="http://yourhostname:port/"></dxrpp-request-options> <dxrpp-callbacks (BeforeRender)="onBeforeRender($event)"></dxrpp-callbacks> </dx-report-parameters-panel> The panel allows you to create custom submit buttons and handle associated click events. This will give you the ability to serialize input parameter values, send them to the backend app, and then apply them to an instance of the XtraReport class (before printing or export operations): * onBeforeRender(event) { this.sender = event.sender; const panel = this.sender.GetParametersModel(); panel.buttons.push({ text: 'Export', onClick: async () => { const data = this.sender.SerializeParametersState(); const formData = new FormData(); formData.append('serializedParameters', data); formData.append('reportUrl', this.reportUrl); const result = await fetch(`${this.host}/ExportWithParameters`, { method: 'POST', body: formData }).then(response => response.json()); alert(result.message); } }, { text: 'Send Email', onClick: () => { alert('Email sent'); } }); panel.showButtons = true; } The following code snippet applies parameter values on the backend: * C# public async Task<IActionResult> ExportWithParameters( [FromServices]IReportParametersSerializer reportParametersSerializer, [FromForm]string serializedParameters, [FromForm]string reportUrl) { var report = await reportParametersSerializer.ApplyParametersStateAsync(reportUrl, serializedParameters); report.ExportToPdf("yourFilePath"); return Ok(new { Message = "A report has been successfully exported" }); } Example #WEB REPORT DESIGNER - HIDE/RESTRICT PARAMETER EDITING We introduced a new set of APIs to help customize edit settings for parameters, parameter groups, and parameter separators. This API will be of value when creating a set of "canned" or predefined reports with mandatory/hidden parameters. The new ParameterEditingSettings class contains the following settings that affect the Properties Panel, Field List and Parameter Editor: * AllowEditParameterCollection - Hides parameter add and delete buttons. * AllowEditParameterGroups - Hides parameter group add and delete buttons. * AllowEditParameterSeparators - Hides parameter separator add and delete buttons. * AllowEditProperties - Disables properties editors for parameter and groups. * AllowReorderParameters - Hides the up and down buttons and disables drag-n-drop operations. The following code snippet turns parameters, parameter groups and separators to read-only for an ASP.NET Core application (users can't add/delete parameters/groups/separators, edit/reorder associated properties): * Razor @{ var designerRender = Html.DevExpress().ReportDesigner("reportDesigner") .ParameterEditingSettings( configure => { configure.AllowEditParameterCollection = false; configure.AllowEditParameterSeparators = false; configure.AllowEditParameterGroups = false; configure.AllowEditProperties = false; configure.AllowReorderParameters = false }) .Height("100%") .Bind("TestReport"); @designerRender.RenderHtml() } We also introduced a new CustomizeParameterProperties event that allows you to customize a specific parameter or disable/hide specific properties editors at the web Report Designer level. For instance, the following code snippet hides the Allow Null Value property editor for all parameters (both in the Properties Panel and Parameter Editor) and hides the delete button for parameter groups: * function customizeParameterProperties(s, e) { if (e.parameter) { let allowNullInfo = e.getEditor('allowNull'); if (allowNullInfo) { allowNullInfo.visible = false; } } if (e.parameterPanelLayoutItem.layoutItemType === 'Group') { e.editOptions.allowDelete = false; } } Documentation REPORTING FOR BLAZOR #REPORT VIEWER - SEND AN EMAIL We created an example that uses the Mailkit library to send an email from our Native Blazor Report Viewer. The "Send Email" button in the Viewer's toolbar opens a DxPopup. In the "Send Email" window, you can specify a recipient list, subject, attachment, and body. Click the "Send" button to send the report with the specified settings. * The DxPopup component is available in ASP.NET & Blazor Subscription. Example ALL PLATFORMS #SVG EXPORT v24.1 ships with a new SVG export option. When enabled, it allows users to save reports as a collection of scalable vector graphics (SVG) images. This new export format will produce high-quality vector report page images without loss of text content quality. SVG export will be of value for those who wish to modify/share report images or embed report thumbnails on web pages (since the SVG format is fully compatible with modern browsers). Export to PNGExport to SVG Open SVG file (Export Result) #NEW EXPRESSION FUNCTIONS We added the following new expression functions to criteria language syntax used in DevExpress Reports: * PrevRowColumnValue(string columnName) — Allows users to retrieve the value of the previous column/row. The function call returns the same record if it is the first record in the data source. * NextRowColumnValue(string columnName) — Allows users to retrieve the value of the next column/row. The function call returns the same record if it is the latest record in the data source. * GroupIndex(int level) — Allows users to retrieve the current group index. * CurrentRowIndexInGroup() — Allows users to retrieve the current row index within a group. Functions are applicable to report control properties whose values can be set via expression binding. They are especially useful when you need to hide first or last records within a group, or highlight these records (i.e., modify appearance properties like Font, BackColor, etc.). Obtaining the group index or the row index within a group is helpful when you need to display group numbering in the group header or record numbering within the group itself. The introduction of PrevRowColumnValue and NextRowColumnValue functions also simplifies migration from Microsoft SSRS and Crystal Reports, where their counterparts exist. The following example generates a report with a multi-level numbered list. To achieve this report layout, report controls use GroupIndex and CurrentRowIndexInGroup functions within data binding expressions (to return group and row indexes). The following image illustrates output for a report designed to group information by product category and discontinued state (Review the following help topic for more information: Group Numbering by Index.): Documentation #PARAMETERS LOCALIZATION ENHANCEMENTS With our built-in DevExpress Reports localization engine, individuals using our Report Designer can now localize the titles of parameter groups displayed within the Parameters Panel across all supported platforms. Descriptions for lookup parameter static values are also localizable. CLOUD DEPLOYMENT #SKIA-BASED GRAPHICS ENGINE (NON-WINDOWS ENVIRONMENT) - PERFORMANCE ENHANCEMENTS We refactored the implementation of our cross-platform drawing engine: we added caching for font internals and optimized dynamic memory allocation. Our internal tests indicate the following improvements when generating a 1500-page text-based report (average of 25 iterations): * Time taken to create a report document has decreased by approximately 20% (9 sec vs. 11 sec). * Time taken to export the report to PDF has decreased by approximately 16% (7.25 sec vs. 8.7 sec). * Time taken to export the report to an image has decreased by approximately 10% (5.2 sec vs. 5.7 sec). We also discovered that the overall CPU usage decreased by approximately 8-10%. Note: Performance enhancements are most pronounced for large report documents with lots of text. #MICROSOFT AZURE AND AMAZON WEB SERVICES APP DEPLOYMENT TUTORIALS We created and published a set of help topics designed to simplify the deployment of DevExpress Reports-powered web apps to Microsoft Azure and AWS. Tutorials include: Microsoft Azure * The deployment of an ASP.NET Core Reporting app via Visual Studio to Azure App Service (Linux) * The deployment of a dockerized ASP.NET Core Reporting app via Visual Studio/CLI to Azure App Service (Linux) * The deployment of an Azure Functions App (Linux-based) with the Reporting capabilities * The usage of the Azure Storage Cache to store report documents Amazon Web Services (AWS): * The deployment of a dockerized ASP.NET Core Reporting app (Linux-based) to AWS Elastic Container Service using the AWS Fargate * The deployment of an AWS Lambda function app * The creation and deployment of a REST API application with Reporting capabilities to AWS Lambda We encourage you to review these new topics: DevExpress Reporting — Cloud Integration. #REPORTING FOR MICROSOFT AZURE — UPDATED REFERENCES We have refactored our internal implementation of services responsible for communicating with the Azure Service Bus and Azure Storage. These services are designed to host multi-instance ASP.NET Web Forms, MVC, and ASP.NET Core web apps with DevExpress Reports on Microsoft Azure. They also allow you to cache report documents in Azure Table and Azure Blob storage. Our implementation now uses the most recent versions of the following NuGet packages. * Azure.Data.Tables v12.8.3 * Azure.Storage.Blobs v7.17.4 * Azure.Messaging.ServiceBus v12.19.1 Documentation: Microsoft Azure Reporting - Implement Custom Storages NuGet Packages: ASP.NET Web Forms & MVC | ASP.NET Core ACCESSIBILITY We now support assistive tools for the following controls: * Native Blazor Report Viewer * JS Report Viewer * WinForms Report Viewer* * WPF Report Viewer* * We are aware of issues and plan to address them in upcoming releases. We have enhanced the accessibility tree to ensure that assistive technologies receive the information they require from user interface elements in accordance with accessibility guidelines outlined in WCAG. Assistive technologies (screen readers) can now access document content in all the controls listed above. The following controls now fully supports keyboard navigation: * Native Blazor Report Viewer * HTML5/JS Report Viewer Users can move through user interface elements and navigate through document content using tab, arrow and special keys. Documentation DATA SOURCES #SQLDATASOURCE WIZARD — TRUST LEVEL CERTIFICATE AND ENCRYPTION OPTIONS Please note that the changes described below are already available in the latest update of our current major version: v23.2.5. We enhanced the user experience in our Data Source Wizard while binding a report to an instance of the MS SQL Server. The data source connection screen now features two new options marked on the screenshot: These new options/changes allow you to avoid the "The certificate chain was issued by an authority that is not trusted" error while binding a report to MS SQL Server database if you cannot set up MS SQL Server differently. Learn more about this error and its cause in the following Microsoft topic: The certificate chain was issued by an authority that isn't trusted - SQL Server (Microsoft Learn). New API Members in Documentation | Reporting — Tutorial #SQLDATASOURCE — POSTGRES DATA DRIVER V7.0 SUPPORT Initially, we hoped to introduce Postgres Stored Procedure support, but discovered that they are mostly useful for update and delete database operations (the SqlDataSource component operates in read-only mode). Instead, we modified our Postgres Database connection and now allow you to bind DevExpress Reports and BI Dashboards to Postgres Functions while using the newest v7.0 database driver. #JSONDATASOURCE — THE USE OF THE SYSTEM.TEXT.JSON NUGET PACKAGE With v24.1, DevExpress Reports and BI Dashboard will utilize functionality from the System.Text.Json assembly/NuGet package (by default). This change was influenced by security considerations and the improved performance offered by Microsoft's built-in library. This package is part of .NET, and this change only pertains to the .NET product line; .NET Framework-based products remain untouched and will continue to use functionality from the Newtonsoft.Json package. If, for any reason, you are unable to utilize System.Text.Json functionality in your .NET-based application, you can set the DevExpress.DataAccess.Native.Json.JsonLoaderHelper.JsonProcessingLibrary* property to NewtonsoftJson and continue using the Newtonsoft.Json library. * Note: We provide this property for backward compatibility purposes. It will be removed from source code in future releases once our migration is complete. We also encourage you to update your applications accordingly. Breaking Change Description: System.Text.Json is used to process the JsonDataSource (DashboardJsonDataSource) component instead of the Newtonsoft.Json library SURVEY - REPORTING YOUR FEEDBACK MATTERS! Please login to complete the survey. SURVEY COMPLETED Thank you for taking the time to complete this survey. Your responses have now been posted. If you want to follow up with additional information, feel free to send us an email at clientservices@devexpress.com anytime. YOU'VE ALREADY COMPLETED THIS SURVEY Our records show that you have already completed this survey. If you want to follow up with additional information, send us an email at clientservices@devexpress.com. THIS SURVEY HAS EXPIRED If you want to share your feedback or request new functionality, please submit a new support ticket via the DevExpress Support Center. We’ll be happy to follow up. BUSINESS INTELLIGENCE DASHBOARD V24.1 * Cascading Parameters * Web Dashboard Enhancements * Data Sources CASCADING PARAMETERS You can now set up cascading parameters to filter the data source or items in a dashboard. The list of values of a dependent parameter now refreshes automatically when you change the value of the parent parameter. When using two parameters, the parent parameter is used to filter the data source for the dependent parameter with dynamic list settings. The following image illustrates cascading parameters where Products parameter values are filtered by the selected Category: Documentation (WinForms) | Documentation (Web) WEB DASHBOARD ENHANCEMENTS #CACHE MANAGEMENT API This update allows you to tailor our built-in BI Dashboard caching engine. Customers encountered several scenarios where our built-in cache needed to be disabled, prompting us to introduce the following API. You can now use the ASPxDashboard.DataSourceCacheEnabled property for Web Forms (or the DashboardConfigurator.DataSourceCacheEnabled property for other web platforms) to disable caching entirely. This forces the DevExpress Dashboard to load the most relevant data whenever a user accesses and views a dashboard. By default, whenever a dashboard parameter value changes, a new data source instance is created and stored in the cache. This impacts memory usage, especially when a parameter doesn't affect data source filtering. As such, we added the ASPxDashboard.DataSourceCacheKeyCreated/ DashboardConfigurator.DataSourceCacheKeyCreated event to prevent the creation of new cache records based on parameter values/available event arguments. For instance, consider the following: * C# DashboardConfigurator.Default.DataSourceCacheKeyCreated += (s, e) => { if(e.Key.DashboardId == "MyDashboard") e.Key.Parameters.Clear(); }; In this scenario, altering a parameter value updates dashboard item data, while reusing the existing data source from the cache without additional fill requests. Furthermore, you can utilize this event to update a specific data source when any interaction with the dashboard takes place: * C# DashboardConfigurator.Default.DataSourceCacheKeyCreated += (s, e) => { if(e.Key.DataSourceId == "dsSales") e.InvalidateCacheRecord(); }; Another use case involves increasing cache key granularity by including groups of users or the users themselves in the cache key. You can utilize the new IDataSourceCacheKey.CustomData property for this purpose. The primary advantage of this strategy is that the key is solely used for creating/retrieving records from the cache and is never exposed on the client side, thus maintaining the security aspect of the implementation: * C# DashboardConfigurator.Default.DataSourceCacheKeyCreated += (s, e) => { e.Key.CustomData.Add("UserId", CurrentUser.UserId); }; #ACCESSIBILITY — KEYBOARD NAVIGATION Keyboard navigation is fully supported for groups and dashboard items. Users can move through user interface elements using tab, arrow and special keys. DATA SOURCES #SQLDATASOURCE WIZARD — TRUST LEVEL CERTIFICATE AND ENCRYPTION OPTIONS Please note that the changes described below are already available in the latest update of our current major version: v23.2.5. We enhanced the user experience in our Data Source Wizard while binding a report to an instance of the MS SQL Server. The data source connection screen now features two new options marked on the screenshot: These new options/changes allow you to avoid the "The certificate chain was issued by an authority that is not trusted" error while binding a report to MS SQL Server database if you cannot set up MS SQL Server differently. Learn more about this error and its cause in the following Microsoft topic: The certificate chain was issued by an authority that isn't trusted - SQL Server (Microsoft Learn). New API Members in Documentation | BI Dashboard — Tutorial #SQLDATASOURCE — POSTGRES DATA DRIVER V7.0 SUPPORT Initially, we hoped to introduce Postgres Stored Procedure support, but discovered that they are mostly useful for update and delete database operations (the SqlDataSource component operates in read-only mode). Instead, we modified our Postgres Database connection and now allow you to bind DevExpress Reports and BI Dashboards to Postgres Functions while using the newest v7.0 database driver. #JSONDATASOURCE — THE USE OF THE SYSTEM.TEXT.JSON NUGET PACKAGE With v24.1, DevExpress Reports and BI Dashboard will utilize functionality from the System.Text.Json assembly/NuGet package (by default). This change was influenced by security considerations and the improved performance offered by Microsoft's built-in library. This package is part of .NET, and this change only pertains to the .NET product line; .NET Framework-based products remain untouched and will continue to use functionality from the Newtonsoft.Json package. If, for any reason, you are unable to utilize System.Text.Json functionality in your .NET-based application, you can set the DevExpress.DataAccess.Native.Json.JsonLoaderHelper.JsonProcessingLibrary* property to NewtonsoftJson and continue using the Newtonsoft.Json library. * Note: We provide this property for backward compatibility purposes. It will be removed from source code in future releases once our migration is complete. We also encourage you to update your applications accordingly. Breaking Change Description: System.Text.Json is used to process the JsonDataSource (DashboardJsonDataSource) component instead of the Newtonsoft.Json library OFFICE FILE API V24.1 Your feedback matters. Please, review the description of DevExpress Office File API-related features below and leave your feedback at the end of the section. Go to the survey now. ACCESSIBILITY ENHANCEMENTS We extended accessibility-related support to the following elements when exporting Word documents to accessible PDF files: * Table of Contents tagging * Metadata fields * Alt text handling * Tables * Floating objects Adobe Acrobat Pro and PDF Accessibility Checker 2024 were used for quality control. Our test documents successfully passed validation for PDF/UA compatibility and WCAG 2.1 compliance. Accessibility-related export enhancements are available out-of-the-box when you specify the PdfUACompatibility option: * C# using System.IO; using DevExpress.XtraRichEdit; // ... RichEditDocumentServer wordProcessor = new RichEditDocumentServer(); //... using(FileStream stream = new FileStream(resultFilePath, FileMode.Create, FileAccess.Write, FileShare.Read)) { PdfExportOptions exportOptions = new PdfExportOptions(); exportOptions.PdfUACompatibility = PdfUACompatibility.PdfUA1; wordProcessor.ExportToPdf(stream, exportOptions); } In addition, we added a Decorative property for both Word Processing Shape and Spreadsheet Shape classes to mark document graphics (pictures, shapes, and charts) as decorative. Decorative shapes add visual interest, but they are not informative. Thus, you do not need to specify Alt Text (meaningful description) for decorative objects when you generate an accessible document. PRINTING ON UNIX-BASED SYSTEMS In this release (v24.1), we added printing support for .NET-based Office File API powered applications running on Unix-based systems. You can now print barcodes, and Word, Excel, and PDF documents in non-Windows environments. We created a new set of APIs that work with the DXPrinterSettings options available in our DevExpress.Drawing library. Use the following new methods to print your documents and barcodes on Unix-based systems: * C# // DevExpress.XtraRichEdit.RichEditDocumentServer: public void Print(DXPrinterSettings printerSettings, string printDocumentName); public void Print(DXPrinterSettings printerSettings); //DevExpress.Spreadsheet.Workbook: public void Print(DXPrinterSettings printerSettings); public void Print(DXPrinterSettings printerSettings, params string[] sheetNames); public void Print(DXPrinterSettings printerSettings, IEnumerable<string> sheetNames); //DevExpress.BarCodes.BarCode: public void Print(DXPrinterSettings printerSettings); For the DevExpress.Pdf.PdfDocumentProcessor class, you still need to call the current Print(PdfPrinterSettings printerSettings) method. To modify print settings, use the new PdfPrinterSettings.DXPrinterSettings option as follows: * C# using DevExpress.Drawing.Printing; using DevExpress.Pdf; // Load a PDF file PdfDocumentProcessor documentProcessor = new PdfDocumentProcessor(); documentProcessor.LoadDocument(@"..\..\Demo.pdf"); // Declare printer settings PdfPrinterSettings pdfPrinterSettings = new PdfPrinterSettings(); // Specify CUPS printer settings DXPrinterSettings dxPrinterSettings = pdfPrinterSettings.DXSettings; dxPrinterSettings.Duplex = DXDuplexMode.DuplexLongEdge; dxPrinterSettings.Copies = 3; // Print the document documentProcessor.Print(pdfPrinterSettings); Note: For Unix-based systems, you need to install the libcups2 package separately. EXPORT DOCUMENTS TO SVG We extended our image export engine and now support SVG images within our Barcode Generation API, Word Processing Document API, and Spreadsheet Document API libraries. With v24.1, you can generate SVG images from your Barcodes, Word document pages and Excel worksheets/cell ranges in both Windows and non-Windows environments. To generate an SVG image from a barcode, create a BarCode class instance, modify settings as necessary and call the BarCode.Save method with DXImageFormat.Svg as a parameter. * C# using (BarCode barCode = new BarCode()) { barCode.Symbology = Symbology.QRCode; barCode.BackColor = Color.White; barCode.ForeColor = Color.Black; barCode.RotationAngle = 0; barCode.CodeBinaryData = Encoding.Default.GetBytes("https://www.devexpress.com/"); barCode.Options.QRCode.CompactionMode = QRCodeCompactionMode.Byte; barCode.Options.QRCode.ErrorLevel = QRCodeErrorLevel.Q; barCode.Options.QRCode.ShowCodeText = false; barCode.DpiX = 72; barCode.DpiY = 72; barCode.Module = 2f; barCode.Save("barcode.svg", DXImageFormat.Svg); } For Word documents, use our new Image Export API - create an RichEditImageExportOptions instance, specify the target DXImageFormat.Svg format using the RichEditImageExportOptions.Format property and call the RichEditDocumentServerExtensions.ExportToImage extension method with the RichEditImageExportOptions object as a parameter. * C# using (var wordProcessor = new RichEditDocumentServer()) { wordProcessor.LoadDocument(@"C:\Documents\Alice.docx"); RichEditImageExportOptions options = new RichEditImageExportOptions(); options.Format = DXImageFormat.Svg; options.PageRange = "1"; wordProcessor.Document.ExportToImage("first_page_image.svg", options); } To export a cell range in an Excel worksheet to an SVG image, call the CellRangeExtensions.ExportToImage method with ImageFileFormat.Svg as a parameter. * C# using (Workbook workbook = new Workbook()) { workbook.LoadDocument("InvestmentPortfolio.xlsx", DevExpress.Spreadsheet.DocumentFormat.Xlsx); Worksheet worksheet = workbook.Worksheets.ActiveWorksheet; worksheet.Range["B18:I30"].ExportToImage("cell_range_image.svg", ImageFileFormat.Svg); } SPREADSHEET DOCUMENT API #JUSTIFY & DISTRIBUTED TEXT ALIGNMENT v24.1 adds support for Justify and Distributed horizontal alignment types within Spreadsheet cells. Excel files using these alignment options can be printed and exported to PDF. You can use the Cell.Alignment.Horizontal property to specify horizontal alignment in code. The following code snippet specifies alignment in code: * C# var workbook = new Workbook(); var worksheet = workbook.Worksheets[0]; Cell cellA1 = worksheet.Cells["A1"]; cellA1.Value = "Justified and top"; cellA1.Alignment.Horizontal = SpreadsheetHorizontalAlignment.Justify; cellA1.Alignment.Vertical = SpreadsheetVerticalAlignment.Top; workbook.ExportToPdf("Result.pdf"); #SORT AND FILTER BY COLOR The DevExpress Spreadsheet Document API ships with enhanced filter and sort-related capabilities. We added new APIs that can sort and filter workbook data by background and font color. Cell ranges filtered/sorted by cell color can be also printed and exported to PDF. Our Sorting APIs include new Worksheet.Sort method overloads designed to sort a specified range by font color or fill setting (background color and pattern). The following code snippet sorts cell values across two cell ranges - the first is sorted by a red font color and the second is sorted by fill settings specified for the first cell in the range: * C# workbook.LoadDocument("sort-filter.xlsx"); Worksheet worksheet = workbook.Worksheets.ActiveWorksheet; // Sort cell range by font color worksheet.Sort(worksheet["B2:B10"], Color.Red); // Sort cell range by fill color worksheet.Sort(worksheet["D2:D10"], worksheet["D2"].Fill); To filter cells by font or background color, you need to apply an auto-filter to the required cell range or table. Once complete, you need to obtain the required column from the AutoFilter.Columns collection and call one of the following methods: * AutoFilterColumn.ApplyFillColorFilter(Color) * AutoFilterColumn.ApplyFillFilter(Fill) * AutoFilterColumn.ApplyFontColorFilter(Color) The following code snippet uses these methods for both cell range and table: * C# workbook.LoadDocument("sort-filter.xlsx"); Worksheet worksheet = workbook.Worksheets.ActiveWorksheet; // Apply an auto-filter to a cell range and filter the first column by font color worksheet.AutoFilter.Apply(worksheet["B1:B10"]); worksheet.AutoFilter.Columns[0].ApplyFontColorFilter(Color.Red); // Create a table, apply an auto-filter and filter the first column by fill color Table table = worksheet.Tables.Add(worksheet["B12:B21"], true); table.AutoFilter.Apply(); table.AutoFilter.Columns[0].ApplyFillColorFilter(Color.Red); In addition, our new APIs allow you to sort data across a filtered range (when auto-filter is enabled) and sort cells by their values/colors simultaneously (using sorting conditions). Documentation: Sort Cell Range by Color PDF DOCUMENT API #LAYERS API v24.1 includes an enhanced PDF Facade API and new APIs designed to manage Optional Content (Layers) visibility in code. Note: A PDF document only stores a default Optional Content configuration. This means that Layer visibility is not preserved when you save the document. Visibility settings are only applicable when you preview the document in the PDF Viewer component or print the document/export it to an image. The new API is available via the PdfDocumentFacade.OptionalContentVisibility property. Access Optional Content groups using the PdfOptionalContentVisibility.Groups collection. To change group visibility, modify the PdfOptionalContentGroupVisibility.Visible property value. The following code snippet changes visibility for Optional Content groups stored in the document and generates print/image output (to preview results): * C# PdfDocumentProcessor processor = new PdfDocumentProcessor(); processor.LoadDocument("layers.pdf"); // Set visibility for each Layer processor.DocumentFacade.OptionalContentVisibility.Groups[0].Visible = false; processor.DocumentFacade.OptionalContentVisibility.Groups[1].Visible = false; processor.DocumentFacade.OptionalContentVisibility.Groups[2].Visible = true; // Print document or export its page to an image to check the result DXBitmap bitmap = processor.CreateDXBitmap(1, 1000); processor.Print(); Documentation: Manage Visibility of Layers (Optional Content Groups) #PDF-A CONVERTER ENHANCEMENTS With this release (v24.1), our PdfDocumentConverter can convert your documents to PDF/A-1b. To create PDF/A-1b documents, pass the PdfCompatibility.PdfA1b value to the Convert method as a parameter. * C# using DevExpress.Pdf; // ... var filePath = "PdfAConversionDemo.pdf"; var converter = new PdfDocumentConverter(filePath); // Convert the file to the Pdf/A1-b format. converter.Convert(PdfCompatibility.PdfA1b); converter.SaveDocument("Result.pdf"); We also added PdfDocumentConverter.PdfACompatibility and PdfDocumentConverter.PdfUACompatibility properties to help obtain the current PDF/A and PDF/UA versions of the document loaded to the converter. WORD PROCESSING DOCUMENT API #MATH EQUATIONS Our Word Processing tools now preserve Math Equations when saving a document. You can import your Word documents with Math Equations in our Word Processing Document API library and save them to the RTF and OpenXml (.docx/.docm) formats without content loss. Note: Math Equations will be printed or exported to PDF only if the source document contains a fallback image for a Math Equation. To suppress Math Equation import, set the DocumentCapabilities.MathEquations property to DocumentCapability.Disabled. #CROSS-PLATFORM IMAGE EXPORT API v24.1 includes new cross-platform APIs to export Word document pages to an image. This new capability allows you to generate document previews in both Windows and non-Windows environments. With our new APIs, you can convert document pages to raster and vector images (PNG, JPEG, BMP, multi-page Tiff, emf), save them as physical files on the disk or obtain a list of image streams for further processing in code. You can also set image background color, modify output image resolution, or generate thumbnail images with a specified size. The new API is available via the RichEditDocumentServerExtensions.ExportToImage extension method of the Document object. Please note that the RichEditDocumentServerExtensions class is defined in the DevExpress.Docs.v24.1.dll assembly. Add this assembly to your project or install the "DevExpress.Document.Processor" NuGet Package to use the RichEditDocumentServerExtensions members. You need a license for the DevExpress Office File API Subscription or DevExpress Universal Subscription to use this class in production code. The following code snippet exports the first document page to an image with a specified size and JPEG format: * C# using DevExpress.XtraRichEdit; using DevExpress.XtraRichEdit.Export.Image; using DevExpress.Drawing; using (var wordProcessor = new RichEditDocumentServer()) { wordProcessor.LoadDocument(@"C:\Documents\Alice.docx"); RichEditImageExportOptions options = new RichEditImageExportOptions(); options.Format = DXImageFormat.Jpeg; options.PageRange = "1"; options.LargestEdgeLength = 1080; wordProcessor.Document.ExportToImage(@"C:\Documents\Image.jpeg", options); } #GUTTER AND MIRRORED MARGINS The DevExpress Word Processing Document API v24.1 allows you to specify gutter margins - extra space that ensures binding will not obscure text on printed pages. You can specify gutter position (top, left, and right) and margin size. Use the Document.GutterAtTop, SectionMargins.GutterPosition, and SectionMargins.Gutter properties to address specific usage requirements. The following code snippet adds a left gutter to the first document section: * C# using DevExpress.XtraRichEdit; using DevExpress.XtraRichEdit.API.Native; using DevExpress.Office.Utils; using (var wordProcessor = new RichEditDocumentServer()) { wordProcessor.LoadDocument(@"Documents//Alice.docx"); Document document = wordProcessor.Document; Section firstSection = wordProcessor.Document.Sections[0]; var pageMargins = firstSection.Margins; pageMargins.GutterPosition = GutterPosition.Left; pageMargins.Gutter = Units.InchesToDocumentsF(1); wordProcessor.SaveDocument("Alice_formatted.docx", DocumentFormat.OpenXml); } Our new Document.MarginType property allows you to define a regular or mirrored margin type. Enable mirrored margins if you print on both sides of the paper and want to bind the printout. The following code snippet enables mirrored margins and specifies an additional space value: * C# using DevExpress.XtraRichEdit; using DevExpress.XtraRichEdit.API.Native; using DevExpress.Office.Utils; using (var wordProcessor = new RichEditDocumentServer()) { wordProcessor.LoadDocument(@"Documents//Alice.docx"); Document document = wordProcessor.Document; // Enable mirrored margins document.MarginsType = MarginsType.Mirrored; foreach (Section section in wordProcessor.Document.Sections) { var pageMargins = section.Margins; // Set the value for mirrored margins pageMargins.Gutter = Units.InchesToDocumentsF(0.5f); } wordProcessor.SaveDocument("Alice_formatted.docx", DocumentFormat.OpenXml); } Documentation SURVEY - OFFICE FILE API YOUR FEEDBACK MATTERS! Please login to complete the survey. SURVEY COMPLETED Thank you for taking the time to complete this survey. Your responses have now been posted. If you want to follow up with additional information, feel free to send us an email at clientservices@devexpress.com anytime. YOU'VE ALREADY COMPLETED THIS SURVEY Our records show that you have already completed this survey. If you want to follow up with additional information, send us an email at clientservices@devexpress.com. THIS SURVEY HAS EXPIRED If you want to share your feedback or request new functionality, please submit a new support ticket via the DevExpress Support Center. We’ll be happy to follow up. .NET MAUI COMPONENTS V24.1 New TreeView Control New Slide View Control New Expander Control New Scroll View Control New Slider Controls Scheduler PDF Viewer Filtering UI HTML Editor Button Orientation-Based Settings Target Plain .NET Optimized Memory Consumption Build Settings Common XAML Namespace DevExpress CRM Demo Survey - .NET MAUI Your feedback matters. Please, review the description of .NET MAUI-related features below and leave your feedback at the end of the section. Go to the survey now. NEW TREEVIEW CONTROL v24.1 includes a new .NET MAUI TreeView control. Designed to present hierarchical data, our .NET MAUI TreeView allows you to create intuitive and visually appealing user interfaces with ease. With our new .NET MAUI TreeView (DXTreeView), you can quickly visualize files structures, organization linked relationships, hierarchical data sets, navigation menus, and more. Our .NET MAUI TreeView ships with the following built-in capabilities: * Hierarchical and self-referential data support * Independent and recursive check box support * Filtering * Sorting * Selection * Swipe items * Item template support Documentation NEW SLIDE VIEW CONTROL v24.1 ships with a new SlideView component - designed to leverage swipe gestures (right/left or up/down) for view navigation. Our .NET MAUI SlideView component can help you create a variety of user interface solutions including application galleries or user tutorial screens. The DevExpress .NET MAUI SlideView includes: * MVVM support (ItemsSource, ItemTemplate, ShowNext/ShowPrevious commands) * Item caching for improved app performance * Horizontal/vertical orientation * Looped and animated navigation Documentation NEW EXPANDER CONTROL This release includes a .NET MAUI Expander (DXExpander) container component to help organize screen content into collapsible/expandable groups. DXExpander supports horizontal and vertical orientation and ships with fluid collapse/expand animation effects. Documentation NEW SCROLL VIEW CONTROL v24.1 includes a new .NET MAUI ScrollView container component designed to help you generate scroll-centric mobile interfaces. With our .NET MAUI ScrollView, users can scroll content across both vertical and horizontal directions. Documentation NEW SLIDER CONTROLS We added two slider controls to our .NET MAUI component suite: * DXSlider — allows users to select a numeric value. * DXRangeSlider — allows users to select a range of numeric values. Features include: * Configurable scale step * Minimum and maximum values * Customizable thumbs, tickmarks, and track * Thumb tooltips Documentation SCHEDULER #AGENDA VIEW Our new .NET MAUI AgendaView component allows you to display schedules, events, and appointments as a single day. Features include: * Ability to hide empty time slots to save screen space * Appointment and header appearance customization options * Built-in button to create a new appointment Documentation PDF VIEWER #DOCUMENT SIGNATURES With v24.1, users can sign PDF documents via our intuitive user interface (users can draw a signature at a given location or select a predefined signature). Signatures can be selected, moved and resized. Users can also specify ink color and line width. Note: To use our .NET MAUI PDF Viewer, you must purchase a separate license (the PDF Viewer is not part of the DevExpress free .NET MAUI offer). To respond to user sign actions, our .NET MAUI PDF Viewer includes the following events: * SignatureCreating / SignatureCreated * SignatureChanged * SignatureDeleting / SignatureDeleted * SignatureSelectionChanged Documentation #TEXT SELECTION Users are now able to select PDF document text and highlight or copy it to the clipboard as requirements dictate. To help facilitate selection, we added a selection context menu that appears when text is selected (the menu includes copy and highlight commands). You can also interact with selected content via new API methods and events. Note: To use our .NET MAUI PDF Viewer, you must purchase a separate license (the PDF Viewer is not part of the DevExpress free .NET MAUI offer). Documentation #TEXT FORMATTING ANNOTATIONS v24.1 allows you to highlight selected text with different markup text annotations. The following text decorations can be added via the interface or API: * Highlight * Underline * Strikethrough * Underline with a wavy line Note: To use our .NET MAUI PDF Viewer, you must purchase a separate license (the PDF Viewer is not part of the DevExpress free .NET MAUI offer). Documentation #GRAPHIC ANNOTATIONS Users can now add annotations to a PDF document, and then comment/collaborate with one another. Our .NET MAUI PDF viewer supports the following annotations: * Sticky notes * Free text * Ellipses (Circle annotations) * Rectangles (Square annotations) * Free-hand drawing Note: To use our .NET MAUI PDF Viewer, you must purchase a separate license (the PDF Viewer is not part of the DevExpress free .NET MAUI offer). Documentation #ACRO FIELDS AcroForms are interactive fields within a PDF document. They allow users to easily fill out forms and can help you gather data. The following AcroForms are included: * Text fields with following attributes supported: input character limit, read-only, multi-line, password. * Check boxes * Radio buttons * List boxes with single and multiple selection support * Combo boxes with single selection support You can also import/export AcroForm data in CSV, XML and FDF formats. Note: To use our .NET MAUI PDF Viewer, you must purchase a separate license (the PDF Viewer is not part of the DevExpress free .NET MAUI offer). Documentation FILTERING UI #PREDEFINED FILTERS v24.1 will ship with a new PredefinedFilterCheckedChipGroupItem component. You can leverage this new UI element to add quick chip filters. Each filter chip allows you to set display text and filter criterion. Common usage scenarios for our optimized .NET MAUI Filter UI/Filter Item include creating favorite user filters or filtering based on a predefined value range. * XAML <ContentPage ... xmlns:dxe="clr-namespace:DevExpress.Maui.Editors;assembly=DevExpress.Maui.Editors"> <!--...--> <dxe:PredefinedFilterCheckedChipGroupItem Text="Price" FieldName="Price" ShowValueCounts="true"> <dx:PredefinedFilter Text="$0 - $500" FilterExpression="?p < 500"/> <dx:PredefinedFilter Text="$500 - $2000" FilterExpression="?p >= 500 AND ?p < 2000"/> <dx:PredefinedFilter Text="$2000+" FilterExpression="?p >= 2000"/> </dxe:PredefinedFilterCheckedChipGroupItem> <!--...--> </ContentPage> Documentation #MULTI-COLUMN LAYOUT The DevExxpress .NET MAUI CollectionView now supports multiple items within any row/column. Our multi-span layout can simplify design if/when collection view items are displayed as cards (allowing you to display more items on screen). For more information, please refer to the following API members: * ItemSpanCount * ItemSpacing * ItemSpanSpacing #RIPPLE EFFECT Our .NET MAUI CollectionView now supports ripple effects for tapped items. Ripple animations can help you create more intuitive user experiences. To activate ripple effects, enable the UseRippleEffect property. #ITEM AND GROUP SEPARATORS Separators are common elements and are used in most collections. With our most recent update, you no longer need to add a separator to your item template. This enhancement simplifies XAML code and template arrangement logic. The following APIs will help you add separators to our .NET MAUI CollectionView: * GroupItemSeparatorColor * GroupItemSeparatorCapMargin * GroupItemSeparatorThickness * ItemSeparatorColor * ItemSeparatorThickness * ItemSeparatorCapMargin * ItemSeparatorShowBeforeGroup HTML EDITOR #TABLES Users can now add and edit tables within our .NET MAUI HTML Editor. Like other DevExpress .NET MAUI controls, user interface elements are designed to maximize ease-of-use on mobile devices/form factors. Documentation BUTTON #RIPPLE EFFECT We added ripple effect support to our .NET MAUI Button component. Use the UseRippleEffect property to activate ripple animations for individual buttons. ORIENTATION-BASED SETTINGS With our new OnOrientation markup extension, it's much easier to implement a responsive UI based on device orientation. There is no need to write C# code and handle orientation changes: you can specify orientation-based settings in XAML. Documentation * XAML <ContentPage ... xmlns:dx="clr-namespace:DevExpress.Maui.Core;assembly=DevExpress.Maui.Core"> <!--...--> <dx:DXButton Content="Click" Padding="{dx:OnOrientation Portrait='10,6', Landscape='12,8'}"/> <!--...--> </ContentPage> TARGET PLAIN .NET As you may know, the XUnit testing library requires standard .NET 8 (not .NET 8.0 Android/iOS) to be referenced as a target framework within project settings. In previous versions, you could not use our controls in a standard .NET 8 project and therefore you could not use XUnit. With v23.2.5, you can target standard .NET 8 in projects when using DevExpress .NET MAUI component libraries. Documentation * XAML <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFrameworks> net8.0;net8.0-android;net8.0-ios </TargetFrameworks> <OutputType Condition="'$(TargetFramework)' != 'net8.0'"> Exe </OutputType> <!-- ... --> </PropertyGroup> <!-- ... --> </Project> OPTIMIZED MEMORY CONSUMPTION With this update, DevExpress .NET MAUI components allow you to ship mobile apps with a significantly lower memory footprint (prevents memory-related issues and improves overall performance). BUILD SETTINGS The DevExpress.Maui.Core NuGet package now includes ".props" and ".targets" files for default build settings. These settings allow you to maximize performance and minimize application size across a variety of usage scenarios. Additionally, they allow you to use Emit as needed (to generate Entity Framework Core classes dynamically). Documentation COMMON XAML NAMESPACE You can now reference all DevExpress .NET MAUI Controls with a single "xmlns:dx="http://schemas.devexpress.com/maui" XAML namespace. To update app XAML, simply use our XamlTool. * v24.1 * Previous Versions <ContentPage ... xmlns:dx="http://schemas.devexpress.com/maui" <ContentPage ... xmlns:dx="clr-namespace:DevExpress.Maui.Core;assembly=DevExpress.Maui.Core" xmlns:dxcv="clr-namespace:DevExpress.Maui.CollectionView;assembly=DevExpress.Maui.CollectionView" xmlns:dxg="clr-namespace:DevExpress.Maui.DataGrid;assembly=DevExpress.Maui.DataGrid" xmlns:dxco="clr-namespace:DevExpress.Maui.Controls;assembly=DevExpress.Maui.Controls" DEVEXPRESS CRM DEMO Our new real-life application demonstrates the following features/capabilities: * Mobile-friendly CRUD flow (using an SQLite database). * Basic and advanced .NET MAUI filtering UI elements. * Master-detail view that leverages the DevExpress .NET MAUI BottomSheet control to display selected item info. * Export .NET MAUI DataGrid data to Excel and PDF. * Import Excel file data and display it within the DevExpress .NET MAUI DataGrid. * Document processing using the DevExpress Office File API library. * Report generation powered by DevExpress Reports. * Material Design 3 theme support. * Data visualization using charts and circular gauge. Download our free demo app from the Google Play Store, TestFlight, or GitHub, and see DevExpress MAUI UI controls in action. Source Code for Demo App (iOS and Android) SURVEY - .NET MAUI YOUR FEEDBACK MATTERS! Please login to complete the survey. SURVEY COMPLETED Thank you for taking the time to complete this survey. Your responses have now been posted. If you want to follow up with additional information, feel free to send us an email at clientservices@devexpress.com anytime. YOU'VE ALREADY COMPLETED THIS SURVEY Our records show that you have already completed this survey. If you want to follow up with additional information, send us an email at clientservices@devexpress.com. THIS SURVEY HAS EXPIRED If you want to share your feedback or request new functionality, please submit a new support ticket via the DevExpress Support Center. We’ll be happy to follow up. XAF: CROSS-PLATFORM .NET APP UI & WEB API V24.1 Blazor – CRUD Blazor – Usability Blazor – Extra Modules Entity Framework Security System Multi-Tenancy Cross-Platform Enhancements Survey - XAF & Web API Service Your feedback matters. Please, review the description of Cross-Platform .NET App UI (XAF) and Web API Service related features below and leave your feedback at the end of the section. Go to the survey now. BLAZOR – CRUD #BATCH / CELL EDIT IN GRID LIST EDITOR Batch Edit support officially ships in XAF Blazor v24.1 via a single option (InlineEditMode = Batch) - much like its XAF WebForms counterpart. Roman Shelomanov We have been testing this since 24.1 EAP and now in 24.1.2 Beta and it works fantastic. Thank you so much for getting it done, it's one extra step to get Blazor to feature parity with WinForms that lots of us have used and loved over the years. #EXPORT DATA FROM GRID LIST EDITOR TO EXCEL WHEN DATAACCESSMODE = SERVER Our Blazor Components and XAF v24.1 support Excel export functionality for grids bound to server-side data (for both EF Core and XPO ORM). To export data to Excel, the DevExpress Blazor Grid will display a loading indicator and download all records from a data source. #ADD NEW FIELDS INTO THE CUSTOMIZATION FORM OF THE GRID AND LAYOUT CONTROLS AT RUNTIME XAF WinForms apps include an Object Model dialog. With it, end-users can search, tick or untick data model fields (including sub-fields and collections), which are not yet displayed in the grid or layout control (as part of the Column Chooser or Customization Form). Much like Microsoft Office apps, this capability allows users to fully customize list and detail forms (based on the structure of a data model). Again, this is helpful when developers need to address changes to business requirements without redeployment. For more information, refer to Runtime Layout Customization in ASP.NET Core Blazor Applications. XAF Blazor v24.1 provides a similar experience for both ListView (Column Chooser) and DetailView (Customization Form). This feature removes the need for many UI customizations in the design-time Model Editor (inside Visual Studio) - something many of you love in XAF WinForms UI. Of course, you can also disable these runtime capabilities for end-users. BLAZOR – USABILITY Philippe Petrussa As mentioned in one of your posts, DevExpress has strongly reduced the boilerplate code to integrate Blazor editors in XAF Blazor. Great Job! #TABBED MDI SUPPORT Tabbed MDI is a multiple document interface (MDI) UI metaphor found in many modern applications (including your favorite Web browser or Microsoft Outlook Web). It is a robust interface that maximizes document screen real estate, especially when working with multiple documents, email messages, etc. Tabbed MDI is enabled in XAF WinForms apps by default, and XAF Blazor provides a similar user experience in v24.1. You can also customize Tabbed MDI in the Model Editor as follows: * Restore previously opened tabs between application runs (RestoreTabbedMdiLayout = True by default). * Refresh View data source on tab focus (RefreshViewOnTabFocus = False by default) * Display or hide tab images (ShowTabImage = True by default) In addition, you can access the underlying tab control in code and configure it as needed using a Controller (in the "SolutionName.Blazor" project). For instance, you can load tabs on demand or simultaneously: * C# protected override void OnFrameAssigned() { base.OnFrameAssigned(); Frame.TemplateChanged += Frame_TemplateChanged; } void Frame_TemplateChanged(object sender, EventArgs e) { if(Frame.Template is ITabbedMdiMainFormTemplate template) { template.TabsModel.RenderMode = DevExpress.Blazor.TabsRenderMode.AllTabs; } } #SIMPLIFIED CREATION OF CUSTOM BLAZOR PROPERTY AND LIST EDITORS In v24.1, we reduced boilerplate code for many popular UI customization scenarios: * Create custom Property and List Editors. * List/Property Editors access control options in code without adapters. Previously, XAF Blazor developers had to create intermediate Component Adapter, Renderer and other boilerplate classes, which were cumbersome or noisy. With this release, the amount of required code is much less (like its XAF WinForms counterpart). Our built-in ComponentModel classes now handle component ValueChanged events (TextChanged, DateChanged, TimeChanged, etc.) and automatically read and write component values (text, date, time, etc.). The minimal implementation of a Blazor property editor based on DxTextBoxModel component model is as follows in v24.1: * C# [PropertyEditor(typeof(string), false)] public class CustomStringPropertyEditor : BlazorPropertyEditorBase { public CustomStringPropertyEditor(Type objectType, IModelMemberViewItem model) : base(objectType, model) { } public override DxTextBoxModel ComponentModel => (DxTextBoxModel)base.ComponentModel; protected override IComponentModel CreateComponentModel() => new DxTextBoxModel(); } Controller code used to customize a List View or DetailView Property Editor control is also simpler in v24.1 (since no adapter is required): * C# public class CustomizeDateEditorController : ViewController<DetailView> { protected override void OnActivated() { base.OnActivated(); View.CustomizeViewItemControl<DateTimePropertyEditor>(this, CustomizeDateTimeEditor); } void CustomizeDateTimeEditor(DateTimePropertyEditor propertyEditor) { // v23.2 //if(propertyEditor.Control is DxDateEditAdapter adapter) { // adapter.ComponentModel.TimeSectionVisible = true; //} // v24.1+ propertyEditor.ComponentModel.TimeSectionVisible = true; } } Our newest Outlook Inspired Demo app contains many custom Property and List Editors. It’s a great source for UX validation/comparison between v23.2 and v24.1. Breaking Change Martin Praxmarer I really love it – I have integrated the new Blazor Progress Bar in nearly 5 minutes – without creating an adapter – nor an razor component! Thank you Guys – simply wonderful! #ACCESSIBILITY ENHANCEMENTS AND KEYBOARD SUPPORT Currently, XAF (UI for ASP.NET Core Blazor, WinForms, and ASP.NET WebForms) ships with partial accessibility support mirroring those found in corresponding DevExpress UI controls across respective UI platforms: * DevExpress ASP.NET Core Blazor * DevExpress WinForms * DevExpress ASP.NET Web Forms * DevExpress DevExtreme (DevExtreme UI controls are used in XAF ASP.NET Core Blazor and ASP.NET Web Forms UI.) XAF Blazor also ships with its own set of UI components/elements (like property editors and action containers). In v24.1, we extended accessibility support and improved keyboard support for all XAF Blazor UI elements (~20% of scenarios). XAF accessibility support will also level up automatically as soon as we enhance accessibility in DevExpress Blazor UI components throughout 2024. Our Blazor Grid's keyboard navigation option also officially ships and is enabled by default in XAF Blazor. Documentation BLAZOR – EXTRA MODULES #SCHEDULER MODULE - SHARED/MULTIPLE RESOURCES The underlying Blazor scheduler component (DxScheduler) supports multiple resources for a scheduler appointment/event in v24.1. XAF Blazor Scheduler module now allows you to use shared resources as well. Previously, only a single resource was allowed in DxScheduler, and XAF displayed a validation error message when you attempted to link multiple resources to an appointment. Documentation #NOTIFICATIONS MODULE SUPPORT XAF Blazor v24.1 supports our Notifications Module. The module allows you to display reminders for scheduler appointments or any custom objects (such as tasks). The detail form for a scheduler appointment/event also allows you to configure reminders like those available in Microsoft Outlook. With the help of the Notifications Module, your app can display a popup window before appointment/event start times. Note: our Notifications module does not have to be bound to the Scheduler module: it can display notifications that originate from anywhere. In the latter instance, your goal as a developer is to provide the notifications service with notification items and the service will process them as required. #MIGRATION TO THE NATIVE BLAZOR REPORT VIEWER In v24.1, XAF's Blazor Reporting Module uses the native Report Viewer for Blazor Server apps (DxReportViewer) instead of a JavaScript-based Report Viewer (DxDocumentViewer). The native report viewer has a number of benefits for XAF Blazor developers: * Support of Size Modes and all Blazor themes * Easier customization without JS using pure C# * Improved performance: Native implementation reduces load time and increases page navigation speed when compared to JavaScript wrapper based reporting tools. Breaking Change Documentation ENTITY FRAMEWORK #EF CORE 8 ORM SUPPORT EF Core 8 support officially ships in v24.1 for XAF and associated Backend Web API Service. EF Core 8 is the latest production-ready version of Entity Framework. While EF Core 8 offers numerous advantages over its predecessor (performance and customization included), it also introduced a series of breaking changes that we needed to address (for instance, DateOnly and TimeOnly support). For more information about recent EF Core updates, refer to the following Microsoft documents: * What's New in EF Core 8 * EF Core 8 Breaking Changes * Performance Benchmarks for EF Core 8 vs XPO ORM #CASCADE DELETION FOR AGGREGATED ONE-TO-MANY COLLECTIONS IN EF CORE With v24.1, XAF's Solution Wizard includes modelBuilder.SetOneToManyAssociationDeleteBehavior(DeleteBehavior.SetNull, DeleteBehavior.Cascade); in the OnModelCreating method of EF Core-based apps. This code will configure "DeleteBehavior.SetNull" for non-aggregated One-to-Many associations and "DeleteBehavior.Cascade" for aggregated One-to-Many associations respectively. Previously, XAF's Aggregated attribute was not considered by EF Core as it was for XPO ORM (and there might be exceptions in certain ListView scenarios). Documentation #NOTEWORTHY EF CORE-RELATED BUG FIXES In addition to new features, we also addressed the following issues in our v24.1 release cycle: * T1217729 - Core – Scheduler Event notifications do not work in EF Core applications * T1230436 - Core - Properties of base classes not included in EF Core's DbContext are missing from the Application Model * T1219872 - Core - Root ListView in the InstantFeedback mode doesn't update modified object data with EF Core * T1204704 - WinForms - Column Header Filters are empty for reference properties with EF Core SECURITY SYSTEM #SINGLE SIGN-ON SUPPORT In v24.1, XAF Blazor and WinForms .NET 6+ apps support Single Sign-On (SSO) natively. Today, modern business apps are integrated with many external systems within organizations. For instance, if an organization uses Microsoft 365, XAF apps are often available at https://myapps.microsoft.com/ among many other apps within this organization. Since XAF Blazor and WinForms .NET 6+ apps (both XPO and EF Core-based) support Microsoft Entra ID and other OAuth2 providers, organizations want/prefer XAF apps to share the same login details or authentication cookies with existing systems/services such as Microsoft Entra SSO. Said differently, organizations require the following: when a user is already authenticated within the organization (for instance, using Microsoft 365), XAF apps must seamlessly work with SSO. Previously, XAF developers had to implement custom solutions to modify XAF’s login form and authentication behavior to support SSO. Important SSO scenarios include, but are not limited to the following: * If a user is NOT logged in within the organization, then XAF apps display a standard OAuth2/SSO provider logon form (just like Teams, Word or Outlook normally does for Microsoft 365). If a user was forced to sign out by administrators, then XAF apps should display the standard logon form as well. * If a user is logged in within the organization (it can be another non-XAF app), then no XAF login form is displayed for the user and focus moves directly to the XAF app UI (by a link from an organization's `Apps dashboard` or via other methods). The logon procedure in an XAF app proceeds automatically behind the scenes (via API calls). XAF users should NOT be forced to explicitly press the “Login with Microsoft” in this instance, because SSO will "just work" as expected. Documentation #BYPASS SECURITY PERMISSION CHECKS FOR INTERNAL BUSINESS LOGIC In addition, it is now possible to call the new SetPropertyValueWithSecurityBypass method from within your BaseObject descendants to bypass security checks for certain protected properties in your internal application logic (custom base classes are also supported). This capability is especially valuable to XAF developers when you wish to set service properties like CreatedBy, ModifiedBy, CreatedOn, UpdatedOn, etc. - our Audit Trail and Model Difference modules operate using a similar mechanism. The SetPropertyValueWithBypassSecurity method can freely set protected properties on behalf of a restricted/regular user in code much like an application administrator - without having to know admin credentials (like impersonation for service tasks). * C# ApplicationUser GetCurrentUser() { return ObjectSpace.GetObjectByKey<ApplicationUser>( ObjectSpace.ServiceProvider.GetRequiredService<ISecurityStrategyBase>().UserId); } public override void OnSaving() { base.OnSaving(); if (ObjectSpace.IsNewObject(this)) { SetPropertyValueWithSecurityBypass(nameof(CreatedBy), GetCurrentUser()); } else { SetPropertyValueWithSecurityBypass(nameof(UpdatedBy), GetCurrentUser()); SetPropertyValueWithSecurityBypass(nameof(UpdatedOn), DateTime.Now); } } As you probably know, this is a long-requested option for many XAFers - an option that prevented full migration from Integrated Mode to Middle Tier Security (because CreateNonsecuredObjectSpace and other workarounds were inconvenient). The SetPropertyValueWithBypassSecurity also includes certain limitations like calling this method is only supported from inside BaseObject.OnSaving (for the best security) or the bypassed property cannot update other protected properties internally. We are of the opinion that this new option will cover 80% of popular use-cases. Breaking Change #ENHANCED PERFORMANCE FOR MIDDLE TIER SECURITY FOR WINFORMS APPS XAF WinForms with Middle Tier Security execute much faster in v24.1. We boosted performance for both EF Core 8 and XPO ORM, as compared to v23.2 (XPO ORM results are even better - a 2.5x improvement). The graphs below show the current duration of batch of performance tests and also individual tests in 24.1 vs v23.2 for EF Core 8. Breaking Change MULTI-TENANCY #EXTEND THE BUILT-IN TENANT CLASS WITH CUSTOM FIELDS You can now extend the standard Tenant class to associate additional data (for instance, module and feature license info) with tenants stored in the application’s Host Database. Of course, you can also access custom Tenant fields in code later (from a Controller or Application Builders). We also supported this for both EF Core and XPO ORM. * C# // MySolution.Module\BusinessObjects\CustomTenant.cs // EF Core using DevExpress.Persistent.BaseImpl.EF.MultiTenancy; public class CustomTenant : Tenant { public virtual string CustomField { get; set; } } // MySolution.Blazor.Server/Startup.cs (MySolution.Win/Startup.cs) builder.AddMultiTenancy() .WithCustomTenantType<CustomTenant>() //... #MIDDLE TIER SECURITY FOR WINFORMS APPS: MULTI-TENANCY AND OAUTH2 SUPPORT In v24.1, XAF WinForms apps (.NET 6+) with Middle Tier Security natively supports Multi-Tenancy and OAuth2 providers (for example, Microsoft Entra ID or Google). Our Outlook Inspired Demo now also uses Middle Tier Security with the Multi-Tenancy module. As we described in our Security Considerations help topic, Windows desktop apps can better meet enterprise security standards with our Middle Tier application server. With our solution, EF Core or XPO developers can retain their standard DbContext or Session and initiate remote connections to a data store from any .NET client (like XAF WinForms or non-XAF apps). This capability is critical within certain environments/business apps (those that cannot maintain direct database connections because of security considerations). Non-XAF EF Core or XPO developers can benefit from our Middle Tier application server and preserve DbContext or Session with their entity data model (learn more). This is especially critical for many desktop .NET developers (WinForms, WPF, WinUI, etc.), who are now required to meet higher security standards. In a nutshell, these developers need to either retrofit/modernize their "fat clients" for Windows (#1) or redo everything from scratch using modern Web technologies and Cloud services (#2). Our Middle Tier Security allows you to choose the "easier" and potentially more reliable route (#1), and to "replace" direct database connections with middleware. Review the following code snippet for more information in this regard: * C# var httpRemoteRepository = new HttpRemoteRepository(httpClient, typeof(EFCoreDbContext).FullName); var optionsBuilder = new DbContextOptionsBuilder<EFCoreDbContext>(); optionsBuilder.UseMiddleTier(opt => opt.UseRemoteRepository(httpRemoteRepository)); optionsBuilder.UseChangeTrackingProxies(); optionsBuilder.UseLazyLoadingProxies(); var dbContextOptions = optionsBuilder.Options; var dbContext = new EFCoreDbContext(dbContextOptions); var users = dbContext.Employees.ToList(); #WEB API SERVICE FOR XAF & NON-XAF UI CLIENTS (POWERED BY EF CORE & XPO ORM) In v24.1, our Backend Web API Service supports Multi-Tenancy for both EF Core and XPO ORM. Our Web API Service has both FREE (basic CRUD) and paid features (such as reporting, audit trail, validation, file attachments, localization, etc). We also distribute many demo applications illustrating the use of free and paid APIs with .NET MAUI, Blazor WebAssembly, JavaScript and even more (for paid features, you must own a DevExpress Universal Subscription license). To learn more about our Web API Service and determine whether it can be of value within your organization, please review the following blog post: Common Questions about the New DevExpress Web API Service (powered by Entity Framework and XPO ORM). CROSS-PLATFORM ENHANCEMENTS #MIGRATION FROM NEWTONSOFT.JSON TO SYSTEM.TEXT.JSON "System.Text.Json" library is now used to deserialize input parameters for Backend Web API Service endpoints. For more information, refer to the following blog post: .NET and .NET Framework — Migration from Newtonsoft.Json to System.Text.Json (v24.1). Breaking Change #SUPPORT OF NEW .NET DATEONLY AND TIMEONLY TYPES FOR EF CORE 8 AND BLAZOR/WINFORMS UI As you probably read in the EF Core 8 breaking changes above, SQL Server date and time now scaffold to .NET DateOnly and TimeOnly, Grid List Editor and associated Date/Time Property Editors in XAF Blazor and WinForms apps for .NET 6+ now support the new .NET types accordingly. The underlying Blazor and WinForms grid components support operations with DateOnly/TimeOnly (sorting, grouping, filtering, including Filter Editors auto filter rows, column header filters) - as will Criteria Language, Server Mode, and other underlying data access components for EF Core. #COMMAND LINE INTERFACE (CLI) SOLUTION WIZARD TEMPLATES XAF v24.1 allows you to use the .NET command line interface (CLI) or the `dotnet` tool to quickly create XAF Blazor and WinForms apps from the console (without using XAF's Solution Wizard). This is similar to the DevExpress Reports implementation: Use .NET CLI Templates. This capability is valuable for XAF developers using Microsoft Visual Studio Code (VS Code) or JetBrains Rider in both Windows and non-Windows development environments (like Linux or MacOS). Previously, these users had to first create XAF projects in Visual Studio for Windows using the Solution Wizard. * CLI dotnet new install DevExpress.XAF.ProjectTemplates::24.1.3 dotnet new dx.xaf -p blazor win -e2e -api Standalone -s MiddleTier -n MyCoolApp cd MyCoolApp dotnet run Documentation #XPO ORM DATA MODEL WIZARD — TRUST LEVEL CERTIFICATE AND ENCRYPTION OPTIONS Please note that the changes described below are already available in the latest update of our current major version: v23.2.5. We enhanced the user experience in our Data Source Wizard while binding a report to an instance of the MS SQL Server. The data source connection screen now features two new options marked on the screenshot: These new options/changes allow you to avoid the "The certificate chain was issued by an authority that is not trusted" error while binding a report to MS SQL Server database if you cannot set up MS SQL Server differently. Learn more about this error and its cause in the following Microsoft topic: The certificate chain was issued by an authority that isn't trusted - SQL Server (Microsoft Learn). SURVEY - XAF & WEB API SERVICE YOUR FEEDBACK MATTERS! Please login to complete the survey. SURVEY COMPLETED Thank you for taking the time to complete this survey. Your responses have now been posted. If you want to follow up with additional information, feel free to send us an email at clientservices@devexpress.com anytime. YOU'VE ALREADY COMPLETED THIS SURVEY Our records show that you have already completed this survey. If you want to follow up with additional information, send us an email at clientservices@devexpress.com. THIS SURVEY HAS EXPIRED If you want to share your feedback or request new functionality, please submit a new support ticket via the DevExpress Support Center. We’ll be happy to follow up. CODERUSH FOR VISUAL STUDIO V24.1 VOICE SUPPORT After you specify Azure Speech Recognition and OpenAI API keys in Voice Setup, you can enable voice features in Visual Studio 2022 and up. Voice setup instructions #VOICE COMMANDS Hold left Ctrl key and speak to trigger voice commands. Examples of things you can say and what they do: * "open foo" - finds and opens Foo.cs file in editor * "class bar" - navigates to classes named "bar" * "bookmark storage" - creates a new bookmark named "storage" * "goto storage" - jumps to a bookmark named "storage" * "show me solution explorer" - shows the Solution Explorer * "line one hundred" - jumps to line 100 in current file Voice commands can use inferred intent, so you don't have to be precise when invoking them. Also, if you're working in large solutions (e.g., with 10,000+ files) the Voice Command for opening files is a huge productivity boost. #VOICE TO CODE Hold right Ctrl and speak to dictate strings, comments, and expressions, and to name identifiers. Examples of what you can create with voice: * A new PascalCase or camelCase identifier name when Visual Studio's Rename refactoring is active. * Dictated strings (including expressions in interpolated strings). * Dictated comments (including indentifier references in comments and paramref and seealso tags in XML Doc comments) Expressions and statements: * Simple expressions, like method and property calls, numbers and binary expressions. * More advanced expressions, like await expressions, null, true and false literals, discards, method calls with out and ref arguments, and assignment statements. #VOICE FOR COPILOT Hold left Ctrl and speak "Hey Copilot!" followed by your query to interact with the GitHub Copilot Chat tool window using your voice. You can use words like "this method" or "this class" to automatically include relevant code in your query. If the Copilot tool window is already active and its chat prompt has focus, you can hold the right Ctrl key down to directly dictate your query into the prompt control (there's no need to start your prompt with "Hey Copilot"). NAVIGATION New quick navigation providers: * MEF Imports - find where the active type is imported. * MEF Exports - find where the active type is exported. * Type - go directly to the type of active variable or property. VCL CONTROLS V24.1 Download Your Copy Today RAD Studio 12.1 Support High DPI Support Data-Aware Controls and Menu Ribbon Control Chart Control Survey - VCL DOWNLOAD YOUR COPY TODAY Once you're ready to upgrade, simply login to the DevExpress Client Center and download the appropriate installer to proceed. Download Free Trial (VCL)VCL Demos v24.1 Your feedback matters. Please, review the description of VCL-related features below and leave your feedback at the end of the section. Go to the survey now. RAD STUDIO 12.1 SUPPORT DevExpress VCL v24.1 and v23.2.6+ officially support Delphi 12.1 and C++ Builder 12.1 (for both 32-bit and 64-bit). If you installed RAD Studio 12.1 previously, please apply its Patch 1, because it addresses the RSS-536 incompatibility issue for the Delphi 64-bit compiler (Blog Post). Also, beware a known performance issue in our Rich Text Editor due to the System.Generics.Defaults unit changes. HIGH DPI SUPPORT #ENHANCED HIGH DPI RESOLUTION AND VECTOR SKIN/IMAGE SUPPORT In addition to new features, we also focus on bug fixes, especially for High DPI-related issues, vector skins, and performance bottlenecks. Ultimately, we want our VCL UI components to be polished, modern, and stand out among all competitors in these aspects (UI matters and this affects almost every VCL customer). Many "fixes" are technically "features". We've recently started to publish more bug reports (for instance, from our internal/private testing) and also include more information into all bug reports such as screenshots before/after and samples - everybody can review this info and analyze the complexity of the work involved. #NEW VECTOR THEME - WINDOWS 11 (WXI) COMPACT We now ship our WXI Compact Skin - a clone of the WXI skin with smaller paddings and margins, which many of you were used to from traditional DevExpress VCL skins such as Bezier, Office, etc. To enable the new WXI Compact Skin, assign WXICompact to the TdxSkinController component's SkinName property. #EASIER SVG ASSIGNMENT FOR IMAGE LISTS AT DESIGN-TIME In v24.1, the DevExpress VCL Ribbon (and other UI controls) allow you to use a single image list for large and small SVG icons. With this capability you can simply specify a small SVG icon and we will scale it up automatically (for instance, in places where the control needs a large icon in the Ribbon). This will improve overall usability and should reduce time spent/maintenance in half. Based on our roadmap survey votes, we made it possible for customers to use both old and new icon assignment strategies using UseRegularAsLarge, LargeSize and related SVG image options. Existing apps and usage habits will remain unaffected. #LAYOUT AND IMAGE MODIFICATIONS IN DESIGN-TIME WIZARDS AND DIALOGS VCL v24.1 includes dozens of layout and `raster to vector` image adjustments in key design-time areas (wizards, designers, and dialogs). High DPI support is crucial and we want to set the highest standards in this regard (in terms of developer usability and speed). DATA-AWARE CONTROLS AND MENU #ACCESSIBILITY ENHANCEMENTS AND KEYBOARD SUPPORT Previous versions of the DevExpress ExpressBars and ExpressNavBar Suite included partial accessibility support (powered by Microsoft Active Accessibility or MSAA). We initially hoped to use MSAA to support remaining VCL controls, but research showed that it is not technically feasible. It turned out that this COM-based technology is outdated for modern accessibility requirements and highly interactive UI controls like ours. Accordingly, we built a new engine for ongoing accessibility-related enhancements (it is powered by Microsoft UI Automation or UIA - used in DevExpress WinForms and WPF products). UIA gave us much more flexibility and allowed to introduce the following accessibility-related v24.1 features: * UIA-powered controls now include Automation options like Name, Description, etc. * UIA-powered controls now include specialized events to customize Automation options at runtime. * UIA-powered controls currently include Button, Check Box, Radio Button, Group Box, Panel, Text Editor, Button Editor, and Label. Our effort in this regard work will continue throughout 2024-2025, and will include enhancements for key unsupported components: * Data grid (key navigation and "read-only" scenarios, likely without data editing and other complex interactions in the first release) * Form layout manager (including layout groups, tabs, etc.) * Navigation and menu (key scenarios in both Ribbon and standard toolbars) * TreeList, Scheduler, Pivot Grid, and other popular data editors (key scenarios in both in-place and standalone editors) #ACCENT-INSENSITIVE OPERATION SUPPORT FOR DATA-AWARE CONTROLS With v24.1, you can configure how various diacritic glyphs in letters (umlauts, grave, acute, and other accents) are treated. For instance, if you type "Joao" in a search box, Data Grid filtering results will include data records with both "João" and "Joao". For more information, read the following quote from Wikipedia: A diacritic (also diacritical mark, diacritical point, diacritical sign, or accent) is a glyph added to a letter or to a basic glyph. The term derives from the Ancient Greek διακριτικός (diakritikós, "distinguishing"), from διακρίνω (diakrī́nō, "to distinguish"). The word diacritic is a noun, though it is sometimes used in an attributive sense, whereas diacritical is only an adjective. Some diacritics, such as the acute ⟨á⟩, grave ⟨à⟩, and circumflex ⟨â⟩ (all shown above an 'a'), are often called accents. Diacritics may appear above or below a letter or in some other position such as within the letter or between two letters. You can enable or configure accent-insensitive operations globally using the TdxDiacriticStringOptions class: * ComparisonMode: allows you to switch between comparison modes (Auto, Sensitive, Insensitive). By default (Sensitive), we do not ignore accents. Insensitive mode can be of value for global organizations with users from different countries/data (for instance, names of employees or goods can be in different languages). * NormalizationMode: specifies the string normalization algorithm (Fast, System) used for string comparison in diacritic-insensitive mode. The default algorithm (Fast) works up to 3 times faster compared to the operating system-dependent algorithm (System). Note: TdxDiacriticStringOptions does not work in Server Mode – use database collation options instead. Impacted text-comparison operations and control features include: * Sorting * Grouping * Incremental search * Auto-filter row * Find panel, etc. This behavior expands to the following controls: * Navigation control * Ribbon and standard toolbars * Lookup editors * Data grid * Pivot grid * Tree list * Other data-bound controls (powered by our Data Controller). #EDITING OPERATIONS (ROTATE, CROP, FLIP, ETC.) IN IMAGE CONTROLS You can now invoke the Image Editor dialog for TcxImage and TcxDBImage components using the Edit context menu command. Our design-time Image Picker dialog includes the new Edit command as well. The Edit command unlocks basic image editing operations: * Crop and straighten * Adjust brightness, contrast and saturation * Mirror * Rotate, etc. The Image Editor maintains operation history and offers both undo and redo functionality. Once the editor is closed and changes are saved, modifications cannot be undone. VCL IMAGEEDIT WITH INTEGRATED IMAGE EDITOR slide 3 of 2 #EXIF METADATA SUPPORT IN IMAGE CONTROLS In v24.1, our image controls (TcxImage and TcxDbImage) read and interpret EXIF metadata from images and modify the image display accordingly. For instance, our image controls automatically rotate the image based on orientation metadata (unlike the standard TImage control and certain image viewers). Impacted image-based scenarios (where rotation will take place) include: * Data Grid cells * TreeList cells * Vertical and Property Grid cells Previously, this required a complex custom solution with a manual call of the Rotate method. Customers who implemented custom solutions on their own (for instance, image rotation in the grid or standalone image editors), can disable this default behavior using a static feature toggle. The TdxGPImage.DefaultImageExifAutoRotation class property value defines if the image editor rotates an image based on EXIF metadata. #FIELD NAME-BASED EXPRESSIONS FOR DATA-AWARE CONTROLS With v24.1, you can use {FieldName} in formula expressions in conditional formatting rules to refer to a field by underlying name instead of a display name. Previously, you could only use a display name/caption or an index. This capability will help you create formulas for conditional formatting rules. This is helpful in VCL apps that support multiple languages or other scenarios where you cannot rely on a field caption (due to its dynamic nature such as translation to another language). Review expression syntax examples for conditional formatting expressions in our Online Documentation. RIBBON CONTROL #OFFICE 365 STYLE FOR VCL RIBBON CONTROL Our VCL Ribbon Control ships with a new Office 365 rendering style. When our new Office 365 style is used, the Ribbon control displays a Search box at the top of the Ribbon form and Show Ribbon options on the bottom right of the Ribbon UI. CHART CONTROL #SECONDARY AXES Secondary axes can be of value if you need to display multiple scales with different measurement units. You can now use SecondaryAxes.AxesX and SecondaryAxes.AxesY properties to add and configure supplemental axes for the main axis of arguments (X-axis) and main axis of values (Y-axis). The following code snippet creates a secondary axis of values and associates it with the first series in an XY diagram. Refer to the TdxChartSecondaryAxes class description for detailed information on available options. * Delphi var ADiagram: TdxChartXYDiagram; AAxisY: TdxChartSecondaryAxisYCollectionItem; AXYSeries: TdxChartXYSeries; begin if dxChartControl1.DiagramCount = 0 then Exit; ADiagram := dxChartControl1.Diagrams[0] as TdxChartXYDiagram; if ADiagram.SeriesCount = 0 then Exit; ASeries := ADiagram.Series[0]; AAxisY := ADiagram.SecondaryAxes.AxesY.Add; ASeries.View.AxisY := AAxisY.Axis; AAxisY.Title.Text := 'Income (USD)'; AAxisY.Title.Alignment := TdxAlignment.Center; AAxisY.Appearance.Color := TdxAlphaColors.Gray; end; #LOGARITHMIC SCALES A logarithmic scale can be of value when you need to display a value range that differs by large orders of magnitude. You can now set the Logarithmic property to True or False to switch between logarithmic and standard numeric scales for the axis (TdxChartCustomAxis). The LogarithmicBase property helps you specify the base of the logarithm (for the logarithmic scale of the axis - default is 10). #POINT AND SEGMENT COLOR CUSTOMIZATION VIA EVENTS You can handle OnGetSeriesPointDrawParameters and OnGetValueLabelDrawParameters events to customize individual series points and associated value labels based on specific conditions. Example #1: Generate unique fill colors for all point markers in the series (Europe's population). * Delphi procedure TFeaturesDemoMainForm.cdLineGetSeriesPointDrawParameters( Sender: TdxChartCustomDiagram; AArgs: TdxChartGetSeriesPointDrawParametersEventArgs); var ALineDrawParameters: TdxChartLineSeriesPointDrawParameters; APalette: TdxChartPalette; APaletteItem: TdxChartPaletteItem; begin APalette := TdxChartStandardPaletteRepository.FindPalette('Slipstream'); if AArgs.SeriesPoint.Series.Caption = 'Europe' then begin if AArgs.DrawParameters.ClassType <> TdxChartLineSeriesPointDrawParameters then Exit; ALineDrawParameters := AArgs.DrawParameters as TdxChartLineSeriesPointDrawParameters; APaletteItem := APalette.GetColorsForIndex(AArgs.SeriesPoint.Index); ALineDrawParameters.MarkerAppearance.FillOptions.Color := APaletteItem.Color; end; end; Example #2: Display different measurement units for value labels (millions or thousands of $). * Delphi procedure TMyForm.cdAreaGetValueLabelDrawParameters(Sender: TdxChartCustomDiagram; AArgs: TdxChartGetValueLabelDrawParametersEventArgs); begin if AArgs.SeriesPoint.Value >= 1000 * 1000 then // Millions AArgs.Text := Format('%.1fM', [AArgs.SeriesPoint.Value / (1000 * 1000)]) else if AArgs.SeriesPoint.Value >= 1000 then // Thousands AArgs.Text := Format('%.0fk', [AArgs.SeriesPoint.Value / 1000]) else AArgs.Text := Format('%0f', [AArgs.SeriesPoint.Value]); end; Review more code examples for Area, Line, Bar, Pie chart views in our Online Documentation. #PALETTES You can now use the Palette property to switch between color palettes whose color sets are applied to individual simple series values and XY series. The following code snippet applies a predefined palette ("Nature Colors") to the chart control: * Delphi dxChartControl1.Palette := TdxChartStandardPaletteRepository.FindPalette('Nature Colors'); You can also add a TdxChartPaletteRepository component to create and manage custom palettes. The following code snippet creates a user palette with three colors and applies the palette to the chart control: * Delphi var AChartPalette: TdxChartUserPalette; begin AChartPalette := dxChartPaletteRepository1.CreateItem; AChartPalette.Name := 'My Palette 1'; // Assigns a unique palette name AChartPalette.Count := 3; // Sets the size of the palette item array AChartPalette.Items[0] := TdxChartPaletteItem.Create(TdxAlphaColors.Red); AChartPalette.Items[1] := TdxChartPaletteItem.Create(TdxAlphaColors.Green); AChartPalette.Items[2] := TdxChartPaletteItem.Create(TdxAlphaColors.Blue); dxChartControl1.Palette := AChartPalette; end; You can also switch between color palettes at runtime, if necessary. You can find more information on predefined and custom palettes in our Online Documentation SURVEY - VCL YOUR FEEDBACK MATTERS! Please login to complete the survey. SURVEY COMPLETED Thank you for taking the time to complete this survey. Your responses have now been posted. If you want to follow up with additional information, feel free to send us an email at clientservices@devexpress.com anytime. YOU'VE ALREADY COMPLETED THIS SURVEY Our records show that you have already completed this survey. If you want to follow up with additional information, send us an email at clientservices@devexpress.com. THIS SURVEY HAS EXPIRED If you want to share your feedback or request new functionality, please submit a new support ticket via the DevExpress Support Center. We’ll be happy to follow up. What's New in v24.1 * General * Accessibility Enhancements * Support of New .NET DateOnly and TimeOnly Types Across UI Platforms * .NET and .NET Framework — Migration from Newtonsoft.Json to System.Text.Json * Regenerate Your NuGet API Key (Feed) * DevExpress NuGet Server - Enhanced Documentation * WinForms * DateOnly & TimeOnly Type Support * Data Grid * TreeList * Accordion * Ribbon & Bars * Data Editors * Document Manager * Docking Library * HTML & CSS Support * PDF Viewer * Rich Text Editor * SVG Scroll Cursor * Spreadsheet * Accessibility and UI Automation * Miscellaneous Enhancements * Performance Improvements * Survey - WinForms * WPF * Accessibility and UI Automation * DateOnly & TimeOnly Type Support * Data Grid * Font Icon Images * Ribbon & Bars * PDF Viewer * Rich Text Editor * Property Grid * Spreadsheet * Lightweight Themes * Survey - WPF * JavaScript & ASP.NET Core * New Splitter Component * UI/UX and API Enhancements * JS Script Size * Angular 18 Support * New DxHttpModule for Angular * Shadow DOM Support (CTP) * Accessibility * ASP.NET Core - DateOnly/TimeOnly Type Support * ASP.NET Core - Data Validation * ASP.NET Core - Rich Text Editor * Survey - JavaScript & ASP.NET Core * Blazor * New TreeList (CTP) * New HTML Editor * New PDF Viewer (CTP) * New Map * New Polar Chart * New Date Range Picker * New DropDown Box * New File Input * New Drawer * New Toast * New Progress Bar * New Bar Gauge * New Sparkline * New Rendering Engine * Keyboard Support * Project Templates * Grid * Charts * New ComboBox and TagBox * List Box * Date Edit & Time Edit * File Management * Form Layout * Rich Text Editor * Scheduler * Window and Popup * Survey - Blazor * Reporting * Reporting for Web * Reporting for Blazor * All Platforms * Cloud Deployment * Accessibility * Data Sources * Survey - Reporting * BI Dashboard * Cascading Parameters * Web Dashboard Enhancements * Data Sources * Office File API * Accessibility Enhancements * Printing on Unix-based Systems * Export Documents to SVG * Spreadsheet Document API * PDF Document API * Word Processing Document API * Survey - Office File API * .NET MAUI * New TreeView Control * New Slide View Control * New Expander Control * New Scroll View Control * New Slider Controls * Scheduler * PDF Viewer * Filtering UI * HTML Editor * Button * Orientation-Based Settings * Target Plain .NET * Optimized Memory Consumption * Build Settings * Common XAML Namespace * DevExpress CRM Demo * Survey - .NET MAUI * XAF - App Framework * Blazor – CRUD * Blazor – Usability * Blazor – Extra Modules * Entity Framework * Security System * Multi-Tenancy * Cross-Platform Enhancements * Survey - XAF & Web API Service * CodeRush * Voice Support * Navigation * VCL * Download Your Copy Today * RAD Studio 12.1 Support * High DPI Support * Data-Aware Controls and Menu * Ribbon Control * Chart Control * Survey - VCL READY TO EVALUATE V24.1? With numerous new products and dozens of high-impact features, v24.1 allows you to build your best, without limits or compromise. Download our fully-functional 30-day trial today and experience the DevExpress difference today. Download Free 30-Day Trial EXPLORE OUR RELEASE HISTORY Learn more about new controls, features, and enhancements across supported platforms (.NET Framework, .NET Core, JavaScript, and VCL) introduced in our previous major updates. What's New in v23.2 What's New in v23.1 What's New in v22.2 Version History CHOOSING THE UI FRAMEWORK FOR DESKTOP & MOBILE CROSS-PLATFORM APPS Choosing the best possible UI framework for a given platform is crucial as it shapes the development process, user experience, and ultimately, the success of the project. Read the blog post Explore our blog posts about v24.1 OFFICE FILE API — ENHANCE ACCESSIBILITY USING OPENAI MODELS Learn how to integrate the OpenAI model into a DevExpress-powered Office File API application and add missing media descriptions and Alt Text. After processing documents, users can export files to accessible PDFs or upload them in a document viewer and read with a screen reader. Read the blog post Explore our blog posts about v24.1 DevExpress Blogs Facebook Twitter YouTube About Us About DevExpressNewsOur AwardsEvents, Meetups and TradeshowsUser Comments and Case StudiesMVP ProgramLogos and Artwork Frequently Asked Questions Product LicensingPurchasing FAQSupported Versions & IDE PrerequisitesSupport PoliciesMaintenance Release FAQ Windows Desktop Controls WinFormsWPFVCLDesktop Reporting Enterprise & Server Tools Business Intelligence DashboardReport & Dashboard ServerOffice File API Mobile Controls .NET MAUI (FREE)Xamarin UI Controls (FREE) Web Controls JS - jQuery, Angular, ReactBlazorASP.NET Web FormsASP.NET MVC and CoreBootstrap Web FormsWeb Reporting Frameworks & Productivity XAF - Cross-Platform .NET App UIXPO - ORM Library (FREE)CodeRush for Visual Studio (FREE).NET App Security & Web API Service (FREE) Testing & QA TestCafe Studio - Web Testing Support & Documentation Search the KBMy QuestionsDocumentationCode ExamplesDemos & Getting StartedBlogsTrainingWhat's New DevExpress engineers feature-complete Presentation Controls, IDE Productivity Tools, Business Application Frameworks, and Reporting Systems for Visual Studio, Delphi, HTML5 or iOS & Android development. Whether using WPF, ASP.NET, WinForms, HTML5 or Windows 10, DevExpress tools help you build and deliver your best in the shortest time possible. We are here to help. Should you have any questions or need assistance from a member of our team, write to us at info@devexpress.com. Use of this site constitutes acceptance of our Website Terms of Use and Privacy Policy (Updated). Cookies Settings Copyright © 1998-2024 Developer Express Inc. All trademarks or registered trademarks are property of their respective owners By clicking “Accept All Cookies”, you agree to the storing of cookies on your device to enhance site navigation, analyze site usage, and assist in our marketing efforts. Accept All Cookies Reject Non-Essential Cookies Cookies Settings PRIVACY PREFERENCE CENTER When you visit a Developer Express Inc (“DevExpress”) website, it may store or retrieve information on your browser, mostly in the form of cookies. This information might be about you, your preferences or your device and is mostly used to make the site work as you expect it to. While the information does not usually directly identify you, it can give you a more personalized web experience. Because DevExpress respects your right to privacy, you can choose to disallow/disable the use of certain cookies. Click on different category headings to learn more and change our default settings. Keep in mind that blocking some types of cookies may impact your experience on the site and may affect the services DevExpress is able to offer to you. You cannot opt-out of our use of strictly necessary cookies as they are used to ensure the proper functioning of our Websites (such as remembering your settings, allowing you to log into your account, and other similar purposes). You may, however, opt-out of receiving and our use of non-essential cookies (including preference, functional, and targeting cookies) by changing your settings for each category listed below. [Videos] Our use of cookies may also collect information about what videos you have watched on our websites. You may opt-out of these cookies by changing your settings for functional and advertising cookies. We will ask you to review and update your choices at least once every two (2) years. By continuing to allow us to use these cookies you explicitly consent to our use of cookies and our disclosure of what videos you have watched on our Websites to our video hosting providers, such as YouTube, for a period of up to two (2) years. Allow All MANAGE CONSENT PREFERENCES STRICTLY NECESSARY COOKIES Always Active These cookies are necessary for the website to function properly and cannot be disabled. They are usually set in response to actions initiated by you – actions that amount to a request for services, such as setting your privacy preferences, logging onto the website, or populating website forms. You can set your browser to block or alert you about these cookies, but certain portions of the site will not work properly when these cookies are disabled. These cookies do not store any personally identifiable information. Cookies Details PERFORMANCE COOKIES Performance Cookies These cookies allow us to count visits and traffic sources so we can measure and improve the performance of our site. They help us understand page popularity and determine how visitors move around the site. All information collected by these cookies are aggregated and therefore anonymous. If you disallow/disable these cookies, we will not know when you have visited our site and we will not be able to monitor its performance. Cookies Details FUNCTIONAL COOKIES Functional Cookies These cookies allow the website to provide enhanced functionality and personalization. They may be set by us or by third party providers whose services we have added to our pages. If you disallow/disable these cookies, some or all of these services may fail to function properly. Cookies Details TARGETING COOKIES Targeting Cookies These cookies may be set through our site by our advertising partners. They may be used by advertising partners to build a profile of your interests and display relevant advertisements on other sites. While these cookies do not store personal information, they do identify your browser and internet device. If you disallow/disable these cookies, you will experience less targeted advertising. Cookies Details Back Button COOKIE LIST Search Icon Filter Icon Clear checkbox label label Apply Cancel Consent Leg.Interest checkbox label label checkbox label label checkbox label label Reject All Confirm My Choices