tag:blogger.com,1999:blog-109950292009-06-24T11:24:55.319-04:00Discovering .NETHere I will post problems I and my colleagues met and solutions we found.Maxim Alexeyevhttp://www.blogger.com/profile/09080974570415524781noreply@blogger.comBlogger63125tag:blogger.com,1999:blog-10995029.post-60494897547113630502009-06-24T11:19:00.003-04:002009-06-24T11:24:55.325-04:00This element is not currently associated with any contextWhen debugging WCF you can see this exception. Some people advice to just <a href="http://ari-techno.blogspot.com/2008/08/this-element-is-not-currently.html">disable stop on exception </a>But it's useful feature.<br /><br />The better is to go into details of this dialog and disable just this specific exception. The only small problem is that it's not in the list. But it's really a small problem. You can add it.<br /><br />Just press "Add..." button, choose "Common Language Runtime Exceptions" from the drop down list and type the exception type, which is <span style="font-family: courier new;">System.Configuration.ConfigurationErrorsException</span>. Now you can disable stopping on just this exception and not all of them.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10995029-6049489754711363050?l=discoveringdotnet.alexeyev.org'/></div>Maxim Alexeyevhttp://www.blogger.com/profile/09080974570415524781noreply@blogger.com0tag:blogger.com,1999:blog-10995029.post-48765457865081061462009-06-05T17:45:00.002-04:002009-06-05T17:48:16.723-04:00Getting output parameters when executing reader in ADO.NETInterestingly, the values of output parameters are not available after ExcecuteReader() is called, even after all records were fetched.<br /><br />To get these values it is required to either close reader (call reader.Close()) or at least call NextResult() method.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10995029-4876545786508106146?l=discoveringdotnet.alexeyev.org'/></div>Maxim Alexeyevhttp://www.blogger.com/profile/09080974570415524781noreply@blogger.com0tag:blogger.com,1999:blog-10995029.post-18705313883416001362009-06-03T15:07:00.005-04:002009-06-03T15:19:36.429-04:00WCF - nullable values are not working in genericsToday I spent couple of hours figuring out why I suddenly got an error "Referenced type 'x`1, ... with data contract name 'xIF_Ph6aZR' in namespace 'x cannot be used since it does not match imported DataContract. Need to exclude this type from referenced types."<br /><br />It was working and what I did just little bit of re-factoring. What I found is that there is a combination of conditions that does not work, while every one of them works separately:<br /><ol><li>Generic class is used as DataContract. </li><li>This class has nullable DataMember property</li><li>You want to reference your class in your client instead of creating in through wsdl.<br /></li></ol><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode">[DataContract]<br /><span class="kwrd">public</span> <span class="kwrd">class</span> DummnyContract&lt;T&gt; where T: IBusinessObject<br />{<br /><br />[DataMember]<br /><span class="kwrd">public</span> DateTime? LastModified{<span class="kwrd">get</span>;<span class="kwrd">set</span>;}<br /><br />}</pre>and then you use it like this:<br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br />[ServiceContract]<br /><span class="kwrd">public</span> <span class="kwrd">interface</span> IService<br />{<br />[OperationContract]<br />DummyContract&lt;int&gt; <span class="kwrd">Get</span>(int id);<br /><br />}</pre><br />This just does not work when you reference your assembly with declaration of this class. You can have it without class being generic. Or, you can have generic without nullable property. But not together.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10995029-1870531388341600136?l=discoveringdotnet.alexeyev.org'/></div>Maxim Alexeyevhttp://www.blogger.com/profile/09080974570415524781noreply@blogger.com0tag:blogger.com,1999:blog-10995029.post-84605504554876945672009-05-02T23:14:00.004-04:002009-05-04T11:13:39.332-04:00WSE and Visual Studio 2008<p>If you got here from search engine you already know that WSE is integrated into Visual Studio 2005, but not 2008. You also know that if add reference to the web service that implements WSE you would get proper class in Visual Studio 2005 but not in 2008. The common advise is use VS 2005 to do the import, or use svcutil.exe.</p> <p>The easiest solution though is just to open Reference.cs file and replace <span style="font-family:courier new;">System.Web.Services.Protocols.SoapHttpClientProtocol</span> with <span style="font-family:courier new;">Microsoft.Web.Services3.WebServicesClientProtocol</span> manually.</p><p>Also, <a href="http://dotnetstep.blogspot.com/2009/04/wse-30-setting-tool-for-visual-studio.html">here</a> you can find how to make plug-in available in VS 2008 UI.<br /></p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10995029-8460550455487694567?l=discoveringdotnet.alexeyev.org'/></div>Maxim Alexeyevhttp://www.blogger.com/profile/09080974570415524781noreply@blogger.com0tag:blogger.com,1999:blog-10995029.post-11092887229934581562009-04-24T20:04:00.001-04:002009-04-24T20:11:33.319-04:00WCF under IIS access problems<p>Today I spent few hours trying to resolve problem with our WCF server for one of our clients. Somehow everything went wrong. Our configuration is WCF server that utilize .NET 3.5, and I set it up to work under IIS6.</p> <p>The errors I got were different, but in result it was all about setting permissions for IIS. Many of them were trivial, but the last one I found tricky. HTTP result code was 500, internal server error, the error in EventViewer said: Could not load file or assembly 'System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=xxx or one of its dependencies. Access denied.</p> <p>Logically, something was wrong with access to \WINDOWS\Microsoft.NET\Framework\v2.0.0.527 folder. However, it was not so. What helped me was adding NT permissions to the folder with my WCF server to the group IIS_WPG. And this is after I tried to add permissions to user ASP_NET… and IUSR_… without success.</p> <div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10995029-1109288722993458156?l=discoveringdotnet.alexeyev.org'/></div>Maxim Alexeyevhttp://www.blogger.com/profile/09080974570415524781noreply@blogger.com0tag:blogger.com,1999:blog-10995029.post-55774313456726169902009-03-04T11:10:00.005-05:002009-03-04T23:33:15.101-05:00Fill WrapPanel from the list (WPF)Sometime, when it is necessary to make a choice from the list, and the list is not that big, it makes sense to use buttons with some actions instead of lists. I found useful technique to do it when the list of actions is dynamic.<br /><br />The idea is somehow populate WrapPanel with buttons dynamically. We can do it by replacing template for ItemsController.<br /><br />I lave a collection of elements (it will be assigned to the ItemsSource property in runtime) with Key and Value properties.<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /><span class="kwrd">&lt;</span><span class="html">ItemsControl</span> <span class="attr">x:Name</span><span class="kwrd">="activitiesControl"</span> <span class="attr">Margin</span><span class="kwrd">="10"</span><span class="kwrd">&gt;</span><br /> <span class="kwrd">&lt;</span><span class="html">ItemsControl.Template</span><span class="kwrd">&gt;</span><br /> <span class="kwrd">&lt;</span><span class="html">ControlTemplate</span><span class="kwrd">&gt;</span><br /> <span class="kwrd">&lt;</span><span class="html">WrapPanel</span> <span class="attr">Width</span><span class="kwrd">="{TemplateBinding Width}"</span> <span class="attr">Height</span><span class="kwrd">="{TemplateBinding Height}"</span> <br /> <span class="attr">FlowDirection</span><span class="kwrd">="LeftToRight"</span> <span class="attr">IsItemsHost</span><span class="kwrd">="true"</span><span class="kwrd">&gt;</span><br /> <span class="kwrd">&lt;/</span><span class="html">WrapPanel</span><span class="kwrd">&gt;</span><br /> <span class="kwrd">&lt;/</span><span class="html">ControlTemplate</span><span class="kwrd">&gt;</span><br /> <span class="kwrd">&lt;/</span><span class="html">ItemsControl.Template</span><span class="kwrd">&gt;</span><br /> <span class="kwrd">&lt;</span><span class="html">ItemsControl.ItemTemplate</span><span class="kwrd">&gt;</span><br /> <span class="kwrd">&lt;</span><span class="html">DataTemplate</span><span class="kwrd">&gt;</span><br /> <span class="kwrd">&lt;</span><span class="html">Button</span> <span class="attr">Style</span><span class="kwrd">="{DynamicResource ActionButton}"</span> <span class="attr">HorizontalAlignment</span><span class="kwrd">="Right"</span> <span class="attr">Margin</span><span class="kwrd">="5"</span> <br /> <span class="attr">Content</span><span class="kwrd">="{Binding Value}"</span> <span class="attr">Width</span><span class="kwrd">="200"</span> <br /> <span class="attr">Command</span><span class="kwrd">="{Binding Path=ViewModel.ActionTypeCommand, <br /> RelativeSource={RelativeSource Mode=FindAncestor, <br /> AncestorType=local:CustomerEditView}}"</span> <span class="attr">CommandParameter</span><span class="kwrd">="{Binding Key}"</span><span class="kwrd">/&gt;</span><br /> <span class="kwrd">&lt;/</span><span class="html">DataTemplate</span><span class="kwrd">&gt;</span><br /> <span class="kwrd">&lt;/</span><span class="html">ItemsControl.ItemTemplate</span><span class="kwrd">&gt;</span><br /><span class="kwrd">&lt;/</span><span class="html">ItemsControl</span><span class="kwrd">&gt;</span></pre><br /><br />Note that I am using Commands. Finally, we have it. Not in Silverlight yet though.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10995029-5577431345672616990?l=discoveringdotnet.alexeyev.org'/></div>Maxim Alexeyevhttp://www.blogger.com/profile/09080974570415524781noreply@blogger.com1tag:blogger.com,1999:blog-10995029.post-43541275325897445012009-03-01T21:35:00.003-05:002009-03-01T21:51:18.335-05:00Application Architecture Guide 2.0I am currently reading <a href="http://www.codeplex.com/AppArchGuide">Application Architecture Guide 2.0</a> I wouldn't say that this is a revolutionary document, but I enjoy reading. I find it very aligned with the way I see the subject, and as it is often the case, it helps me organize my thoughts by putting everything into it's place.<br /><br />One of the things I would recommend this paper for is it's not just theory or collection of "design patterns". With all my respect for the latter, many authors just abuse the term and sound very far from real world of day-to-day developers. Here I find some practical advices, key points that should not be missed when creating application architecture and common mistakes. There is also understanding of the real world by acknowledgment that development became "agile". And again, the term is not abused.<br /><br />The volume is quite big, and there are many repetitions, so I just somewhere in the first quarter of the document. Hopefully the last three quarters will be as good as first one.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10995029-4354127532589744501?l=discoveringdotnet.alexeyev.org'/></div>Maxim Alexeyevhttp://www.blogger.com/profile/09080974570415524781noreply@blogger.com0tag:blogger.com,1999:blog-10995029.post-32468684374603237382009-03-01T21:24:00.002-05:002009-03-01T21:34:38.550-05:00Binding to nullable values (WPF)I don't usually use nullable types, since my approach is to use them only when there is real difference between zero and null values, and it's not often when such difference exists. However, sometimes you may not really know how the value is going to be used. And then having it nullable may be preferable.<br /><br />That was the case in one of our custom projects. Naturally, you would want to display empty edit box for null value, which was defined as nullable integer. The problem is that by default binding would not handle empty string as null value. Fortunately, with .NET 3.5 SP1 there is a way. You should use TargetNullValue attribute. The binding would look like this then:<br /><br /><pre class="csharpcode"><br />{Binding Path=Customer.ClientYear, TargetNullValue={x:Static sys:String.Empty}}</pre><br />This, and other attributes for the binding collected in one document <a href="http://go.nbdtech.com/?94E138EA">here</a><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10995029-3246868437460323738?l=discoveringdotnet.alexeyev.org'/></div>Maxim Alexeyevhttp://www.blogger.com/profile/09080974570415524781noreply@blogger.com0tag:blogger.com,1999:blog-10995029.post-2212335150694901172009-02-17T23:39:00.004-05:002009-02-17T23:45:31.491-05:00Flickering in WinFormsI used to know these things long time ago. But later, with .NET programming they faded in my memory and it took me more than an hour (I will not tell you how much more) of experimenting to discover it again.<br /><br />When your screen is flickering, check if DoubleBuffered is on. It may help.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10995029-221233515069490117?l=discoveringdotnet.alexeyev.org'/></div>Maxim Alexeyevhttp://www.blogger.com/profile/09080974570415524781noreply@blogger.com0tag:blogger.com,1999:blog-10995029.post-86411837533374683472009-02-15T19:12:00.004-05:002009-02-15T20:20:25.139-05:00Implementing netTcpBinding in WCF and securityUsually I post when I solve some problem. I didn't solve this one yet, but was almost there.<br /><br />We decided to build n-tier application using CSLA. So, this is a desktop WPF application, we just host a server with business objects and desktop client access the server through Internet. I wanted to use WCF for communication. Also, I wanted to host it in my own windows service, not by IIS. Additionally, I wanted to use TCP binding, as it is supposedly faster, if I understand correctly, which is another reason to not use IIS.<br /><br />It looked very simple, like all I had to do is to change binding to NetTcpBinding. And first, it worked fine until I tried to connect from my home computer, which wasn't member of our Windows domain. It looked that for some reason connection was terminated by the host. The error message did not give me any specifics. Using SvcTraceViewer.exe I identified the problem as related to the security.<br /><br />Making the long story short, I found <a href="http://www.rcs-solutions.com/blog/2008/11/06/CustomAuthenticationAndEncryptionWithWCF.aspx">this blog post </a>to be the best to help me with my problem. The last step of getting certificate value did not work for me, and the project is on hold now. I hope I will find the time to resolve everything.<br /><br />Now, let me explain in few words what the problem is. All bindings with exceptions of BasicHttpBinding require some kind of security on the transport level. So, we have to create certificate and apply it somehow. We could register it in the Windows, but I didn't want to go this way.<br /><br />Another problem is authentication. If I hosted service under IIS, that would provide some mechanism, but this is not what I wanted. To help with that I decided to use custom username authentication. And this is also covered very well in post I found.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10995029-8641183753337468347?l=discoveringdotnet.alexeyev.org'/></div>Maxim Alexeyevhttp://www.blogger.com/profile/09080974570415524781noreply@blogger.com1tag:blogger.com,1999:blog-10995029.post-11073185295215485622009-01-15T00:01:00.002-05:002009-01-15T01:07:27.536-05:00Smart ClientsAbout four years ago I heard about Smart Clients. Back then this term had particular meaning. Application can be considered Smart Client applications if<ul><li>It's a desktop application with rich user interface.</li><li>As desktop application, it can work in disconnected mode.</li><li>When connected, additional functionality may be available.</li></ul>I thought that it was a great idea and truly believed that such kinds of application would become highly popular. Instead, what we can see is an unprecedented rise of web applications.<br /><br />I still like all these ideas, and still think that the idea of smart client application is valid. But it worth to analyze what went wrong with them, and why web became so popular. Well, analysis may be a too strong word, just some thought.<br /><br />One of the reasons, I believe, is that it's much easier to develop web application than occasionally connected desktop application. There are so many people involved in web development now, that the choice of technologies, frameworks and examples is huge. In result, there is a new generation of developers who never developed anything by web applications. And these process feeds itself, the more popular web development is, the easier it becomes.<br /><br />Another reason is that desktop applications were not that good looking. Somehow web became more visually appealing. Why did it happen? For one thing, desktop application development stuck with Win32 windows. (I have to mention that my view are based on my experience, which is development for Windows OS). As much as I love .NET, all we had for user interface were WinForms, and this is just the wrapper around old Win32 windows, where presentation cannot be easily separated from development, by which I mean coding. It's different in Web. HTML, with it's styles, allowed to developers to develop, and designers to design. And these are different talents.<br /><br />Finally, it appears that many applications just don't need neither rich UI nor ability to work being disconnected. There is just no benefits for them in that.<br /><br />So, where do we go now? Is it time to bury the idea? After all, even the term Smart Client is deluded. Every desktop application can be named Smart Client today, and I even heard the term applied to a web application with Java applet as a client, that just cannot work disconnected at all. I would argue that we should not just write it off yet. Here is why.<br /><br /><span style="font-weight: bold;">Trends</span>. Let's look at where web applications are going. Many of them remind desktop applications now. Not only very rich UI is available through JavaScript, Flash, or Silverlihgt, but because they are starting to store their data on a client machine. Just look at such things as <a href="http://gears.google.com/">Google Gears</a>, or Isolated Storage in Silverlight, I am sure there are others.<br /><br /><span style="font-weight: bold;">WPF</span> gives desktop developers what web developers had long time ago. Presentation is finally separated from implementation. Layout of application is not part of the code anymore. With tools like Expression Blend designer can do his job while developer does his. And the results can finally be better than what they are in Web. There are concerns here. After all, WPF is not exactly new already, and adaptation is not going really fast. I would suggest that one of the reason is that XAML is too complicated, another is there are no tools on the market that could much those available for web designers. Expression Blend is definitely not there yet. Hopefully, the latter is just the matter of time, and once those tools are available, the complexity of the XAML will be hidden from designers.<br /><br />Bottom line, I am optimistic about Smart Client applications. The deployment can be simplified with technologies like ClickOnes, or similar. Automatic updates are already a must. Disconnected mode is not that critical now, but having local cache is easier to do with existing light weight databases. WPF will bring pretty look. Sure, there are so many applications that just belong to web, there are those that can be better with smart clients, particulary business applications (emails, data entry applications, any office application).<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10995029-1107318529521548562?l=discoveringdotnet.alexeyev.org'/></div>Maxim Alexeyevhttp://www.blogger.com/profile/09080974570415524781noreply@blogger.com1tag:blogger.com,1999:blog-10995029.post-38802135285375376962009-01-12T00:00:00.004-05:002009-01-12T00:15:04.530-05:00Lazy loading for CSLA lists to support Server mode in DevExpress Grid. Part 4The last parts are processing DataFetch based on LazyLoadingCriteriaBase class, which is defined as:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="rem">/// &lt;summary&gt;</span><br /> <span class="rem">/// </span><br /> <span class="rem">/// &lt;/summary&gt;</span><br /> <span class="kwrd">public</span> <span class="kwrd">enum</span> LoadingCommand<br /> {<br /> <span class="rem">/// &lt;summary&gt;</span><br /> <span class="rem">/// </span><br /> <span class="rem">/// &lt;/summary&gt;</span><br /> DoNothing,<br /> <span class="rem">/// &lt;summary&gt;</span><br /> <span class="rem">/// </span><br /> <span class="rem">/// &lt;/summary&gt;</span><br /> FetchData,<br /> <span class="rem">/// &lt;summary&gt;</span><br /> <span class="rem">/// </span><br /> <span class="rem">/// &lt;/summary&gt;</span><br /> LoadIds,<br /> <span class="rem">/// &lt;summary&gt;</span><br /> <span class="rem">/// </span><br /> <span class="rem">/// &lt;/summary&gt;</span><br /> ChangeSorting<br /> };<br /><br /> <span class="rem">/// &lt;summary&gt;</span><br /> <span class="rem">/// Used to control fetching for lazy loading</span><br /> <span class="rem">/// &lt;/summary&gt;</span><br /> [Serializable]<br /> <span class="kwrd">public</span> <span class="kwrd">class</span> LazyLoadingCriteriaBase<br /> {<br /> <span class="kwrd">private</span> LoadingCommand _command;<br /> <span class="kwrd">private</span> List&lt;<span class="kwrd">object</span>&gt; _idList;<br /> <span class="kwrd">private</span> ListSortDescriptionCollection _sortInfo;<br /><br /> <span class="rem">/// &lt;summary&gt;</span><br /> <span class="rem">/// Constructor</span><br /> <span class="rem">/// &lt;/summary&gt;</span><br /> <span class="rem">/// &lt;param name="command"&gt;&lt;/param&gt;</span><br /> <span class="kwrd">public</span> LazyLoadingCriteriaBase(LoadingCommand command)<br /> {<br /> _command = command;<br /> }<br /><br /> <span class="rem">/// &lt;summary&gt;</span><br /> <span class="rem">/// Only ids should be fetched</span><br /> <span class="rem">/// &lt;/summary&gt;</span><br /> <span class="kwrd">public</span> LoadingCommand Command<br /> {<br /> get { <span class="kwrd">return</span> _command; }<br /> }<br /> <span class="rem">/// &lt;summary&gt;</span><br /> <span class="rem">/// Only objects with ids from the list should be loaded</span><br /> <span class="rem">/// &lt;/summary&gt;</span><br /> <span class="kwrd">public</span> List&lt;<span class="kwrd">object</span>&gt; IdList<br /> {<br /> get<br /> {<br /> <span class="kwrd">return</span> _idList;<br /> }<br /> set<br /> {<br /> _idList = <span class="kwrd">value</span>;<br /> }<br /> }<br /> <span class="rem">/// &lt;summary&gt;</span><br /> <span class="rem">/// Apply sorting when loading</span><br /> <span class="rem">/// &lt;/summary&gt;</span><br /> <span class="kwrd">public</span> ListSortDescriptionCollection SortInfo<br /> {<br /> get<br /> {<br /> <span class="kwrd">return</span> _sortInfo;<br /> }<br /> set<br /> {<br /> _sortInfo = <span class="kwrd">value</span>;<br /> }<br /> }<br /> }<br /></pre><br /><br />I believe you got the idea at this point and will not put that example. Generally, at the moment you would need to modify you SQL statements to process sorting and filter items with required primary keys.<br /><br />The last step is mapping our interface to IListServer, but that's again, just trivial mapper.<br /><br />One more thing. You may notice some hints of multi-threading, like locking controller, flags, etc. That part was not completed, just ignore it.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10995029-3880213528537537696?l=discoveringdotnet.alexeyev.org'/></div>Maxim Alexeyevhttp://www.blogger.com/profile/09080974570415524781noreply@blogger.com1tag:blogger.com,1999:blog-10995029.post-45119779923337662582009-01-11T23:55:00.002-05:002009-01-11T23:59:51.709-05:00Lazy loading for CSLA lists to support Server mode in DevExpress Grid. Part 3Now, when we have LazyLoaderController here is what was done in ExtendedBindingList.<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="preproc">#region</span> Lazy loading<br /> <span class="kwrd">private</span> LazyLoadingController _lazyLoadingController;<br /> <span class="kwrd">private</span> <span class="kwrd">int</span> _loadingWindowSize = 100;<br /> <span class="kwrd">private</span> <span class="kwrd">int</span> _deletedIndex = -1;<br /> <span class="kwrd">private</span> <span class="kwrd">bool</span> _useTheading = <span class="kwrd">false</span>;<br /> <span class="kwrd">private</span> <span class="kwrd">bool</span> _isFetched = <span class="kwrd">false</span>;<br /><br /> <span class="rem">/// &lt;summary&gt;</span><br /> <span class="rem">/// Change size of loading window (number of records to be loaded)</span><br /> <span class="rem">/// &lt;/summary&gt;</span><br /> <span class="rem">/// &lt;param name="loadingWindowSize"&gt;&lt;/param&gt;</span><br /> <span class="kwrd">protected</span> <span class="kwrd">void</span> ChangeLoadingWindowSize(<span class="kwrd">int</span> loadingWindowSize)<br /> {<br /> _loadingWindowSize = loadingWindowSize;<br /> }<br /> <span class="rem">/// &lt;summary&gt;</span><br /> <span class="rem">/// Fetch data into current list</span><br /> <span class="rem">/// &lt;/summary&gt;</span><br /> <span class="rem">/// &lt;param name="creatria"&gt;&lt;/param&gt;</span><br /> <span class="kwrd">protected</span> <span class="kwrd">virtual</span> <span class="kwrd">void</span> FetchData(<span class="kwrd">object</span> creatria)<br /> {<br /> <span class="kwrd">throw</span> <span class="kwrd">new</span> Exception(<span class="str">"FetchMoreData is not implemented"</span>);<br /> }<br /><br /> <span class="kwrd">protected</span> <span class="kwrd">void</span> SetFetched()<br /> {<br /> _isFetched = <span class="kwrd">true</span>;<br /> }<br /><br /> <span class="kwrd">protected</span> <span class="kwrd">bool</span> IsFetched<br /> {<br /> get { <span class="kwrd">return</span> _isFetched; }<br /> }<br /><br /> <span class="rem">/// &lt;summary&gt;</span><br /> <span class="rem">/// Load more records into current list if necessary to support </span><br /> <span class="rem">/// window around particular element</span><br /> <span class="rem">/// &lt;/summary&gt;</span><br /> <span class="rem">/// &lt;param name="index"&gt;defines what objects should be loaded (+/- window size/2)&lt;/param&gt;</span><br /> <span class="kwrd">private</span> <span class="kwrd">void</span> FetchNewWindow(<span class="kwrd">int</span> index)<br /> {<br /> <span class="kwrd">if</span> (_lazyLoadingController != <span class="kwrd">null</span>)<br /> {<br /> <span class="kwrd">lock</span> (_lazyLoadingController)<br /> {<br /> <span class="kwrd">int</span> startingIndex = index - (_loadingWindowSize / 2);<br /> <span class="kwrd">if</span> (startingIndex &lt; 0)<br /> startingIndex = 0;<br /> List&lt;<span class="kwrd">object</span>&gt; idList = _lazyLoadingController.GetUnloadedIdList(startingIndex, _loadingWindowSize);<br /> <span class="kwrd">if</span> ((idList != <span class="kwrd">null</span>) &amp;&amp; (idList.Count &gt; 0))<br /> {<br /> LazyLoadingCriteriaBase criteria = <span class="kwrd">new</span> LazyLoadingCriteriaBase(LoadingCommand.FetchData);<br /> criteria.IdList = idList;<br /> FetchData(criteria);<br /> }<br /> }<br /> }<br /> }<br /><br /> <span class="kwrd">private</span> <span class="kwrd">void</span> FetchObject(<span class="kwrd">object</span> id)<br /> {<br /> List&lt;<span class="kwrd">object</span>&gt; idList = <span class="kwrd">new</span> List&lt;<span class="kwrd">object</span>&gt;(1);<br /> idList.Add(id);<br /> LazyLoadingCriteriaBase criteria = <span class="kwrd">new</span> LazyLoadingCriteriaBase(LoadingCommand.FetchData);<br /> criteria.IdList = idList;<br /> FetchData(criteria);<br /> }<br /> <span class="rem">/// &lt;summary&gt;</span><br /> <span class="rem">/// Get unique id for child object.</span><br /> <span class="rem">/// &lt;/summary&gt;</span><br /> <span class="rem">/// &lt;param name="item"&gt;&lt;/param&gt;</span><br /> <span class="rem">/// &lt;returns&gt;&lt;/returns&gt;</span><br /> <span class="kwrd">protected</span> <span class="kwrd">virtual</span> <span class="kwrd">object</span> GetItemId(<span class="kwrd">object</span> item)<br /> {<br /> <span class="kwrd">if</span> (item <span class="kwrd">is</span> IIdObject)<br /> <span class="kwrd">return</span> ((IIdObject)item).Id;<br /> <span class="kwrd">else</span><br /> <span class="kwrd">return</span> item.GetHashCode();<br /> }<br /><br /> <span class="kwrd">protected</span> <span class="kwrd">virtual</span> DateTime GetItemLastModified(T item)<br /> {<br /> <span class="kwrd">if</span> (item <span class="kwrd">is</span> IIdObject)<br /> <span class="kwrd">return</span> ((IIdObject)item).LastModified;<br /> <span class="kwrd">else</span><br /> <span class="kwrd">return</span> DateTime.MinValue;<br /> }<br /><br /> <span class="rem">/// &lt;summary&gt;</span><br /> <span class="rem">/// Remove Id of the object. Called internally when object removed</span><br /> <span class="rem">/// &lt;/summary&gt;</span><br /> <span class="rem">/// &lt;param name="id"&gt;&lt;/param&gt;</span><br /> <span class="kwrd">protected</span> <span class="kwrd">void</span> RemoveId(<span class="kwrd">object</span> id)<br /> {<br /> <span class="kwrd">if</span> (_lazyLoadingController != <span class="kwrd">null</span>)<br /> <span class="kwrd">lock</span> (_lazyLoadingController)<br /> {<br /> _lazyLoadingController.RemoveId(id);<br /> }<br /> }<br /> <span class="rem">/// &lt;summary&gt;</span><br /> <span class="rem">/// Turn lazy loading on. Should be called before first fetch is done</span><br /> <span class="rem">/// &lt;/summary&gt;</span><br /> <span class="kwrd">protected</span> <span class="kwrd">void</span> SetLazyLoading(<span class="kwrd">bool</span> useTheading)<br /> {<br /> <span class="kwrd">if</span> (_lazyLoadingController == <span class="kwrd">null</span>)<br /> {<br /> _lazyLoadingController = <span class="kwrd">new</span> LazyLoadingController();<br /> <span class="rem">// multithreading doesn't work well yet</span><br /> <span class="rem">// _useTheading = useTheading; </span><br /> }<br /> }<br /> <span class="rem">/// &lt;summary&gt;</span><br /> <span class="rem">/// Is LazyLoading turned on</span><br /> <span class="rem">/// &lt;/summary&gt;</span><br /> <span class="kwrd">public</span> <span class="kwrd">bool</span> IsLazyLoading<br /> {<br /> get { <span class="kwrd">return</span> (_lazyLoadingController != <span class="kwrd">null</span>); }<br /> }<br /> <span class="rem">/// &lt;summary&gt;</span><br /> <span class="rem">/// Some loading may be done in separate thread when lazy loading is used. </span><br /> <span class="rem">/// &lt;/summary&gt;</span><br /> <span class="kwrd">protected</span> <span class="kwrd">bool</span> UseThreading<br /> {<br /> get { <span class="kwrd">return</span> _useTheading; }<br /> }<br /><br /> <span class="rem">/// &lt;summary&gt;</span><br /> <span class="rem">/// Adds Id of the object to the list. Object is not loaded yet. Should be called</span><br /> <span class="rem">/// when ids are loaded</span><br /> <span class="rem">/// &lt;/summary&gt;</span><br /> <span class="rem">/// &lt;param name="id"&gt;if true, no check for existing id is done, better performance&lt;/param&gt;</span><br /> <span class="kwrd">protected</span> <span class="kwrd">void</span> AddId(<span class="kwrd">object</span> id, <span class="kwrd">bool</span> knownNew, DateTime lastModified)<br /> {<br /> <span class="kwrd">if</span> (_lazyLoadingController != <span class="kwrd">null</span>)<br /> {<br /> <span class="kwrd">lock</span> (_lazyLoadingController)<br /> {<br /> _lazyLoadingController.AddId(id, knownNew, lastModified);<br /> }<br /> }<br /> }<br /><br /> <span class="rem">/// &lt;summary&gt;</span><br /> <span class="rem">/// Called internally when object is loaded</span><br /> <span class="rem">/// &lt;/summary&gt;</span><br /> <span class="rem">/// &lt;param name="id"&gt;&lt;/param&gt;</span><br /> <span class="rem">/// &lt;param name="item"&gt;&lt;/param&gt;</span><br /> <span class="kwrd">protected</span> <span class="kwrd">void</span> LoadObject(<span class="kwrd">object</span> id, T item)<br /> {<br /> <span class="kwrd">if</span> (_lazyLoadingController != <span class="kwrd">null</span>)<br /> <span class="kwrd">lock</span> (_lazyLoadingController)<br /> {<br /> _lazyLoadingController.LoadObject(id, item);<br /> }<br /> }<br /><br /> <span class="rem">/// &lt;summary&gt;</span><br /> <span class="rem">/// Used internally</span><br /> <span class="rem">/// &lt;/summary&gt;</span><br /> <span class="kwrd">protected</span> <span class="kwrd">void</span> ClearIds()<br /> {<br /> <span class="kwrd">if</span> (_lazyLoadingController != <span class="kwrd">null</span>)<br /> <span class="kwrd">lock</span> (_lazyLoadingController)<br /> {<br /> _lazyLoadingController.Clear();<br /> }<br /> }<br /><br /> <span class="rem">/// &lt;summary&gt;</span><br /> <span class="rem">/// Adds object to the list of loaded objects</span><br /> <span class="rem">/// &lt;/summary&gt;</span><br /> <span class="rem">/// &lt;param name="index"&gt;&lt;/param&gt;</span><br /> <span class="rem">/// &lt;param name="item"&gt;&lt;/param&gt;</span><br /> <span class="kwrd">protected</span> <span class="kwrd">override</span> <span class="kwrd">void</span> SetItem(<span class="kwrd">int</span> index, T item)<br /> {<br /> <span class="kwrd">base</span>.SetItem(index, item);<br /> <span class="kwrd">object</span> id = GetItemId(item);<br /> LoadObject(id, item);<br /> DateTime lastModified = GetItemLastModified(item);<br /> <span class="kwrd">if</span> (lastModified &gt; _lastModified)<br /> _lastModified = lastModified;<br /> }<br /><br /> <span class="rem">/// &lt;summary&gt;</span><br /> <span class="rem">/// Adds object to the list of loaded objects</span><br /> <span class="rem">/// &lt;/summary&gt;</span><br /> <span class="rem">/// &lt;param name="index"&gt;&lt;/param&gt;</span><br /> <span class="rem">/// &lt;param name="item"&gt;&lt;/param&gt;</span><br /> <span class="kwrd">protected</span> <span class="kwrd">override</span> <span class="kwrd">void</span> InsertItem(<span class="kwrd">int</span> index, T item)<br /> {<br /> <span class="kwrd">object</span> id = GetItemId(item);<br /> LoadObject(id, item);<br /> DateTime lastModified = GetItemLastModified(item);<br /> <span class="kwrd">if</span> (lastModified &gt; _lastModified)<br /> _lastModified = lastModified;<br /> <span class="kwrd">base</span>.InsertItem(index, item);<br /> }<br /> <span class="rem">/// &lt;summary&gt;</span><br /> <span class="rem">/// Need to override to call ILazyLoading.ListChanged with proper indexes</span><br /> <span class="rem">/// &lt;/summary&gt;</span><br /> <span class="rem">/// &lt;param name="e"&gt;&lt;/param&gt;</span><br /> <span class="kwrd">protected</span> <span class="kwrd">override</span> <span class="kwrd">void</span> OnListChanged(ListChangedEventArgs e)<br /> {<br /> <span class="kwrd">base</span>.OnListChanged(e);<br /> <span class="kwrd">if</span> (_listChanged != <span class="kwrd">null</span>)<br /> {<br /> <span class="kwrd">int</span> newIndex;<br /> <span class="kwrd">int</span> oldIndex;<br /><br /> <span class="kwrd">if</span> (_lazyLoadingController != <span class="kwrd">null</span>)<br /> {<br /> <span class="kwrd">lock</span> (_lazyLoadingController)<br /> {<br /> <span class="kwrd">if</span> (e.NewIndex &lt; 0)<br /> newIndex = e.NewIndex;<br /> <span class="kwrd">else</span><br /> {<br /> <span class="kwrd">if</span> (e.ListChangedType == ListChangedType.ItemDeleted)<br /> {<br /> <span class="kwrd">if</span> (_deletedIndex &lt; 0)<br /> <span class="kwrd">throw</span> <span class="kwrd">new</span> Exception(<span class="str">"Index for ListchangeType.ItedDeleted is not defined for ILazyLoading.ListChanged"</span>);<br /> newIndex = _deletedIndex;<br /> _deletedIndex = -1;<br /> }<br /> <span class="kwrd">else</span><br /> {<br /> <span class="kwrd">object</span> item = <span class="kwrd">this</span>[e.NewIndex];<br /> <span class="kwrd">object</span> id = GetItemId(item);<br /> newIndex = _lazyLoadingController.GetObjectIndex(id);<br /> }<br /> }<br /> <span class="kwrd">if</span> (e.OldIndex &lt; 0)<br /> oldIndex = e.OldIndex;<br /> <span class="kwrd">else</span><br /> {<br /> <span class="kwrd">if</span> (e.OldIndex == e.NewIndex)<br /> oldIndex = newIndex;<br /> <span class="kwrd">else</span><br /> <span class="kwrd">throw</span> <span class="kwrd">new</span> Exception(<span class="str">"ListChangedEventArgs.OldIndex not supported in for ILazyLoading.ListChanged"</span>);<br /> }<br /> }<br /> }<br /> <span class="kwrd">else</span><br /> {<br /> newIndex = e.NewIndex;<br /> oldIndex = e.OldIndex;<br /> }<br /> ListChangedEventArgs e2;<br /> <span class="kwrd">if</span> (e.PropertyDescriptor != <span class="kwrd">null</span>)<br /> e2 = <span class="kwrd">new</span> ListChangedEventArgs(e.ListChangedType, newIndex, e.PropertyDescriptor);<br /> <span class="kwrd">else</span><br /> e2 = <span class="kwrd">new</span> ListChangedEventArgs(e.ListChangedType, newIndex, oldIndex);<br /> _listChanged(<span class="kwrd">this</span>, e2);<br /> }<br /> }<br /> <span class="rem">/// &lt;summary&gt;</span><br /> <span class="rem">/// Load object by Id if not found. Useful only when LazyLoading is on</span><br /> <span class="rem">/// &lt;/summary&gt;</span><br /> <span class="rem">/// &lt;param name="id"&gt;&lt;/param&gt;</span><br /> <span class="rem">/// &lt;returns&gt;&lt;/returns&gt;</span><br /> <span class="kwrd">protected</span> <span class="kwrd">object</span> GetObjectyById(<span class="kwrd">object</span> id)<br /> {<br /> <span class="kwrd">if</span> (_lazyLoadingController != <span class="kwrd">null</span>)<br /> {<br /> <span class="kwrd">lock</span> (_lazyLoadingController)<br /> {<br /> <span class="kwrd">object</span> obj = _lazyLoadingController.GetObject(id);<br /> <span class="kwrd">if</span> (obj == <span class="kwrd">null</span>)<br /> {<br /> FetchObject(id);<br /> obj = _lazyLoadingController.GetObject(id);<br /> }<br /> <span class="kwrd">return</span> obj;<br /> }<br /> }<br /> <span class="kwrd">return</span> <span class="kwrd">null</span>;<br /><br /> }<br /><br /> <span class="preproc">#region</span> ILazyLoading Members<br /> <span class="kwrd">int</span> ILazyLoading.Count<br /> {<br /> get<br /> {<br /> <span class="kwrd">if</span> (_lazyLoadingController != <span class="kwrd">null</span>)<br /> <span class="kwrd">lock</span> (_lazyLoadingController)<br /> {<br /> <span class="kwrd">if</span> (!IsFetched)<br /> {<br /> LazyLoadingCriteriaBase criteria = <span class="kwrd">new</span> LazyLoadingCriteriaBase(LoadingCommand.LoadIds);<br /> FetchData(criteria);<br /> }<br /> <span class="kwrd">return</span> (_lazyLoadingController.Count);<br /> }<br /> <span class="kwrd">else</span><br /> <span class="kwrd">return</span> Count;<br /> }<br /> }<br /> <span class="kwrd">object</span> ILazyLoading.<span class="kwrd">this</span>[<span class="kwrd">int</span> index]<br /> {<br /> get<br /> {<br /> <span class="kwrd">if</span> (_lazyLoadingController != <span class="kwrd">null</span>)<br /> {<br /> <span class="kwrd">lock</span> (_lazyLoadingController)<br /> {<br /> <span class="kwrd">object</span> id;<br /> <span class="kwrd">object</span> obj;<br /> _lazyLoadingController.GetObjectInfo(index, <span class="kwrd">out</span> obj, <span class="kwrd">out</span> id);<br /> <span class="kwrd">if</span> (obj == <span class="kwrd">null</span>)<br /> {<br /> FetchNewWindow(index);<br /> _lazyLoadingController.GetObjectInfo(index, <span class="kwrd">out</span> obj, <span class="kwrd">out</span> id);<br /> <span class="kwrd">if</span> (obj == <span class="kwrd">null</span>)<br /> <span class="kwrd">throw</span> <span class="kwrd">new</span> Exception(<span class="str">"Lazy loading didn't work, object supposed to be loaded"</span>);<br /> }<br /> <span class="kwrd">return</span> obj;<br /> }<br /> }<br /> <span class="kwrd">else</span><br /> <span class="kwrd">return</span> <span class="kwrd">this</span>[index];<br /> }<br /> set<br /> {<br /> <span class="kwrd">throw</span> <span class="kwrd">new</span> Exception(<span class="str">"The method or operation is not implemented."</span>);<br /> }<br /> }<br /> <span class="kwrd">object</span> ILazyLoading.GetRowKey(<span class="kwrd">int</span> index)<br /> {<br /> <span class="kwrd">if</span> (_lazyLoadingController != <span class="kwrd">null</span>)<br /> {<br /> <span class="kwrd">lock</span> (_lazyLoadingController)<br /> {<br /> <span class="kwrd">object</span> obj;<br /> <span class="kwrd">object</span> id;<br /> _lazyLoadingController.GetObjectInfo(index, <span class="kwrd">out</span> obj, <span class="kwrd">out</span> id);<br /> <span class="kwrd">return</span> id;<br /> }<br /> }<br /> <span class="kwrd">else</span><br /> {<br /> <span class="kwrd">return</span> GetItemId(<span class="kwrd">this</span>[index]);<br /> }<br /> }<br /> <span class="kwrd">int</span> ILazyLoading.GetRowIndex(<span class="kwrd">object</span> key)<br /> {<br /> <span class="kwrd">if</span> (_lazyLoadingController != <span class="kwrd">null</span>)<br /> <span class="kwrd">lock</span> (_lazyLoadingController)<br /> {<br /> <span class="kwrd">return</span> _lazyLoadingController.GetObjectIndex(key);<br /> }<br /> <span class="kwrd">else</span><br /> {<br /> <span class="kwrd">for</span> (<span class="kwrd">int</span> i = 0; i &lt; Count; i++)<br /> {<br /> <span class="kwrd">if</span> (GetItemId(<span class="kwrd">this</span>[i]) == key)<br /> <span class="kwrd">return</span> i;<br /> }<br /> <span class="kwrd">return</span> -1;<br /> }<br /> }<br /> <span class="kwrd">int</span> ILazyLoading.Add(<span class="kwrd">object</span> <span class="kwrd">value</span>)<br /> {<br /> <span class="kwrd">if</span> (_lazyLoadingController != <span class="kwrd">null</span>)<br /> {<br /> <span class="kwrd">lock</span> (_lazyLoadingController)<br /> {<br /> ((IList)<span class="kwrd">this</span>).Add(<span class="kwrd">value</span>);<br /> <span class="kwrd">object</span> id = GetItemId(<span class="kwrd">value</span>);<br /> <span class="kwrd">return</span> _lazyLoadingController.GetObjectIndex(id);<br /> }<br /> }<br /> <span class="kwrd">else</span><br /> <span class="kwrd">return</span> ((IList)<span class="kwrd">this</span>).Add(<span class="kwrd">value</span>);<br /><br /> }<br /> <span class="kwrd">bool</span> ILazyLoading.Contains(<span class="kwrd">object</span> <span class="kwrd">value</span>)<br /> {<br /> <span class="kwrd">if</span> (_lazyLoadingController != <span class="kwrd">null</span>)<br /> {<br /> <span class="kwrd">lock</span> (_lazyLoadingController)<br /> {<br /> <span class="kwrd">object</span> id = GetItemId(<span class="kwrd">value</span>);<br /> <span class="kwrd">return</span> _lazyLoadingController.GetObjectIndex(id) &gt;= 0;<br /> }<br /> }<br /> <span class="kwrd">else</span><br /> <span class="kwrd">return</span> ((IList)<span class="kwrd">this</span>).Contains(<span class="kwrd">value</span>);<br /> }<br /> <span class="kwrd">int</span> ILazyLoading.IndexOf(<span class="kwrd">object</span> <span class="kwrd">value</span>)<br /> {<br /> <span class="kwrd">if</span> (_lazyLoadingController != <span class="kwrd">null</span>)<br /> {<br /> <span class="kwrd">lock</span> (_lazyLoadingController)<br /> {<br /> <span class="kwrd">object</span> id = GetItemId(<span class="kwrd">value</span>);<br /> <span class="kwrd">return</span> _lazyLoadingController.GetObjectIndex(id);<br /> }<br /> }<br /> <span class="kwrd">else</span><br /> <span class="kwrd">return</span> ((IList)<span class="kwrd">this</span>).IndexOf(<span class="kwrd">value</span>);<br /> }<br /> <span class="kwrd">void</span> ILazyLoading.Insert(<span class="kwrd">int</span> index, <span class="kwrd">object</span> <span class="kwrd">value</span>)<br /> {<br /> <span class="kwrd">if</span> (_lazyLoadingController != <span class="kwrd">null</span>)<br /> {<br /><br /> }<br /> <span class="kwrd">else</span><br /> ((IList)<span class="kwrd">this</span>).Insert(index, <span class="kwrd">value</span>);<br /> }<br /> <span class="kwrd">bool</span> ILazyLoading.IsFixedSize<br /> {<br /> get<br /> {<br /> <span class="kwrd">return</span> ((IList)<span class="kwrd">this</span>).IsFixedSize;<br /> }<br /> }<br /> <span class="kwrd">bool</span> ILazyLoading.IsReadOnly<br /> {<br /> get<br /> {<br /> <span class="kwrd">return</span> ((IList)<span class="kwrd">this</span>).IsReadOnly;<br /> }<br /> }<br /> <span class="kwrd">void</span> ILazyLoading.Remove(<span class="kwrd">object</span> <span class="kwrd">value</span>)<br /> {<br /> ((IList)<span class="kwrd">this</span>).Remove(<span class="kwrd">value</span>);<br /> }<br /> <span class="kwrd">void</span> ILazyLoading.ApplySort(ListSortDescriptionCollection sortInfo)<br /> {<br /> <span class="kwrd">if</span> (_lazyLoadingController != <span class="kwrd">null</span>)<br /> {<br /> <span class="kwrd">lock</span> (_lazyLoadingController)<br /> {<br /> LazyLoadingCriteriaBase criteria = <span class="kwrd">new</span> LazyLoadingCriteriaBase(LoadingCommand.ChangeSorting);<br /> criteria.SortInfo = sortInfo;<br /> FetchData(criteria);<br /> }<br /> }<br /> }<br /> <span class="kwrd">private</span> ListChangedEventHandler _listChanged;<br /> <span class="kwrd">event</span> ListChangedEventHandler ILazyLoading.ListChanged<br /> {<br /> add { _listChanged += <span class="kwrd">value</span>; }<br /> remove { _listChanged -= <span class="kwrd">value</span>; }<br /> }<br /> <span class="preproc">#endregion</span><br /> <span class="preproc">#endregion</span><br /><br /> <span class="preproc">#region</span> LastModified<br /> <span class="kwrd">private</span> DateTime _lastModified = DateTime.MinValue;<br /> <span class="rem">/// &lt;summary&gt;</span><br /> <span class="rem">/// Maximum from children's LastModified</span><br /> <span class="rem">/// &lt;/summary&gt;</span><br /> <span class="kwrd">public</span> DateTime LastModified<br /> {<br /> get<br /> {<br /> <span class="kwrd">if</span> (_lazyLoadingController != <span class="kwrd">null</span>)<br /> {<br /> <span class="kwrd">if</span> (_lazyLoadingController.LastModified &gt; _lastModified)<br /> <span class="kwrd">return</span> _lazyLoadingController.LastModified;<br /> }<br /> <span class="kwrd">return</span> _lastModified;<br /> }<br /> }<br /> <span class="preproc">#endregion</span><br /></pre><br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="rem">/// &lt;summary&gt;</span><br /> <span class="rem">/// Remove the item at the</span><br /> <span class="rem">/// specified index.</span><br /> <span class="rem">/// &lt;/summary&gt;</span><br /> <span class="rem">/// &lt;param name="index"&gt;</span><br /> <span class="rem">/// The zero-based index of the item</span><br /> <span class="rem">/// to remove.</span><br /> <span class="rem">/// &lt;/param&gt;</span><br /> <span class="kwrd">protected</span> <span class="kwrd">override</span> <span class="kwrd">void</span> RemoveItem(<span class="kwrd">int</span> index)<br /> {<br /> <span class="preproc">#region</span> Lazy loading<br /> <span class="kwrd">object</span> item = <span class="kwrd">this</span>[index];<br /> <span class="kwrd">object</span> id = GetItemId(item);<br /> <span class="kwrd">if</span> (_lazyLoadingController != <span class="kwrd">null</span>)<br /> _deletedIndex = _lazyLoadingController.GetObjectIndex(id);<br /> <span class="kwrd">else</span><br /> _deletedIndex = -1;<br /> <span class="preproc">#endregion</span><br /><br /> OnRemovingItem(<span class="kwrd">this</span>[index]);<br /> <span class="kwrd">base</span>.RemoveItem(index);<br /><br /> <span class="preproc">#region</span> Lazy loading<br /> RemoveId(id);<br /> <span class="preproc">#endregion</span><br /> }<br /></pre><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10995029-4511977992333766258?l=discoveringdotnet.alexeyev.org'/></div>Maxim Alexeyevhttp://www.blogger.com/profile/09080974570415524781noreply@blogger.com0tag:blogger.com,1999:blog-10995029.post-10278086647917927542009-01-11T23:46:00.002-05:002009-01-11T23:55:09.733-05:00Lazy loading for CSLA lists to support Server mode in DevExpress Grid. Part 2The general idea behind this approach was fetching primary keys first and requesting objects later. My test showed that it was many times faster to fetch primary keys into the list comparing to fetching all fields and creating objects, which wasn't a surprise.<br /><br />The supporting class was created that would store the mapping between primary keys and fetched objects. That was pretty simple class:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="rem">/// &lt;summary&gt;</span><br /> <span class="rem">/// Controls if object is loaded</span><br /> <span class="rem">/// &lt;/summary&gt;</span><br /> [Serializable]<br /> <span class="kwrd">public</span> <span class="kwrd">class</span> LazyLoadingController<br /> {<br /> [Serializable]<br /> <span class="kwrd">private</span> <span class="kwrd">class</span> ObjectInfo<br /> {<br /> <span class="kwrd">public</span> <span class="kwrd">object</span> _id;<br /> <span class="kwrd">public</span> <span class="kwrd">object</span> _loadedObject = <span class="kwrd">null</span>;<br /><br /> <span class="kwrd">public</span> ObjectInfo(<span class="kwrd">object</span> id)<br /> {<br /> _id = id;<br /> }<br /> <span class="kwrd">public</span> ObjectInfo(<span class="kwrd">object</span> id, <span class="kwrd">object</span> loadedObject)<br /> {<br /> _id = id;<br /> _loadedObject = loadedObject;<br /> }<br /> }<br /> [Serializable]<br /> <span class="kwrd">private</span> <span class="kwrd">class</span> ObjectInfoList : KeyedCollection&lt;<span class="kwrd">object</span>, ObjectInfo&gt;<br /> {<br /> <span class="kwrd">protected</span> <span class="kwrd">override</span> <span class="kwrd">object</span> GetKeyForItem(ObjectInfo item)<br /> {<br /> <span class="kwrd">return</span> item._id;<br /> }<br /> }<br /><br /> <span class="preproc">#region</span> Variables<br /> <span class="kwrd">private</span> ObjectInfoList _idList = <span class="kwrd">new</span> ObjectInfoList();<br /> <span class="kwrd">private</span> DateTime _lastModified = DateTime.MinValue;<br /> <span class="preproc">#endregion</span><br /><br /> <span class="preproc">#region</span> Public methods<br /> <span class="kwrd">public</span> DateTime LastModified<br /> {<br /> get { <span class="kwrd">return</span> _lastModified; }<br /> }<br /> <span class="rem">/// &lt;summary&gt;</span><br /> <span class="rem">/// Adds Id to the list</span><br /> <span class="rem">/// &lt;/summary&gt;</span><br /> <span class="rem">/// &lt;param name="id"&gt;&lt;/param&gt;</span><br /> <span class="rem">/// &lt;returns&gt;&lt;/returns&gt;</span><br /> <span class="kwrd">public</span> <span class="kwrd">void</span> AddId(<span class="kwrd">object</span> id, <span class="kwrd">bool</span> knownNew, DateTime lastModified)<br /> {<br /> <span class="kwrd">if</span> (knownNew || !_idList.Contains(id))<br /> {<br /> _idList.Add(<span class="kwrd">new</span> ObjectInfo(id));<br /> <span class="kwrd">if</span> (lastModified &gt; _lastModified)<br /> _lastModified = lastModified;<br /> }<br /> }<br /> <span class="rem">/// &lt;summary&gt;</span><br /> <span class="rem">/// Adds Id to the list if needed, and marks object as loaded</span><br /> <span class="rem">/// &lt;/summary&gt;</span><br /> <span class="rem">/// &lt;param name="id"&gt;&lt;/param&gt;</span><br /> <span class="rem">/// &lt;param name="loadedObject"&gt;&lt;/param&gt;</span><br /> <span class="rem">/// &lt;returns&gt;&lt;/returns&gt;</span><br /> <span class="kwrd">public</span> <span class="kwrd">void</span> LoadObject(<span class="kwrd">object</span> id, <span class="kwrd">object</span> loadedObject)<br /> {<br /> <span class="kwrd">if</span> (_idList.Contains(id))<br /> {<br /> ObjectInfo objInfo = _idList[id];<br /> objInfo._loadedObject = loadedObject;<br /> }<br /> <span class="kwrd">else</span><br /> {<br /> _idList.Add(<span class="kwrd">new</span> ObjectInfo(id, loadedObject));<br /> DateTime lastModified = GetObjectLastModified(loadedObject);<br /> <span class="kwrd">if</span> (lastModified &gt; _lastModified)<br /> _lastModified = lastModified;<br /> }<br /> }<br /><br /> <span class="kwrd">private</span> DateTime GetObjectLastModified(<span class="kwrd">object</span> obj)<br /> {<br /> <span class="kwrd">if</span> (obj <span class="kwrd">is</span> IIdObject)<br /> <span class="kwrd">return</span> ((IIdObject)obj).LastModified;<br /> <span class="kwrd">else</span><br /> <span class="kwrd">return</span> DateTime.MinValue;<br /> }<br /> <span class="rem">/// &lt;summary&gt;</span><br /> <span class="rem">/// Removes id and related object from list</span><br /> <span class="rem">/// &lt;/summary&gt;</span><br /> <span class="rem">/// &lt;param name="id"&gt;&lt;/param&gt;</span><br /> <span class="kwrd">public</span> <span class="kwrd">void</span> RemoveId(<span class="kwrd">object</span> id)<br /> {<br /> _idList.Remove(id);<br /> }<br /> <span class="rem">/// &lt;summary&gt;</span><br /> <span class="rem">/// Marks object as not loaded</span><br /> <span class="rem">/// &lt;/summary&gt;</span><br /> <span class="rem">/// &lt;param name="id"&gt;&lt;/param&gt;</span><br /> <span class="kwrd">public</span> <span class="kwrd">void</span> UnLoadObject(<span class="kwrd">object</span> id)<br /> {<br /> <span class="kwrd">if</span> (_idList.Contains(id))<br /> _idList[id]._loadedObject = <span class="kwrd">null</span>;<br /> }<br /><br /> <span class="rem">/// &lt;summary&gt;</span><br /> <span class="rem">/// Gets id and object by index</span><br /> <span class="rem">/// &lt;/summary&gt;</span><br /> <span class="rem">/// &lt;param name="index"&gt;&lt;/param&gt;</span><br /> <span class="rem">/// &lt;param name="loadedObject"&gt;&lt;/param&gt;</span><br /> <span class="rem">/// &lt;param name="id"&gt;&lt;/param&gt;</span><br /> <span class="kwrd">public</span> <span class="kwrd">void</span> GetObjectInfo(<span class="kwrd">int</span> index, <span class="kwrd">out</span> <span class="kwrd">object</span> loadedObject, <span class="kwrd">out</span> <span class="kwrd">object</span> id)<br /> {<br /> IList list = _idList <span class="kwrd">as</span> IList;<br /> ObjectInfo info = list[index] <span class="kwrd">as</span> ObjectInfo;<br /> loadedObject = info._loadedObject;<br /> id = info._id;<br /> }<br /> <span class="rem">/// &lt;summary&gt;</span><br /> <span class="rem">/// Gets index and object by id</span><br /> <span class="rem">/// &lt;/summary&gt;</span><br /> <span class="rem">/// &lt;param name="id"&gt;&lt;/param&gt;</span><br /> <span class="kwrd">public</span> <span class="kwrd">object</span> GetObject(<span class="kwrd">object</span> id)<br /> {<br /> <span class="kwrd">if</span> (_idList.Contains(id))<br /> <span class="kwrd">return</span> _idList[id]._loadedObject;<br /> <span class="kwrd">else</span><br /> <span class="kwrd">return</span> <span class="kwrd">null</span>;<br /> }<br /> <span class="rem">/// &lt;summary&gt;</span><br /> <span class="rem">/// Gets index by id</span><br /> <span class="rem">/// &lt;/summary&gt;</span><br /> <span class="rem">/// &lt;param name="id"&gt;&lt;/param&gt;</span><br /> <span class="rem">/// &lt;returns&gt;&lt;/returns&gt;</span><br /> <span class="kwrd">public</span> <span class="kwrd">int</span> GetObjectIndex(<span class="kwrd">object</span> id)<br /> {<br /> <span class="kwrd">if</span> (_idList.Contains(id))<br /> {<br /> ObjectInfo objInfo = _idList[id];<br /> <span class="kwrd">return</span> _idList.IndexOf(objInfo);<br /> }<br /> <span class="kwrd">else</span><br /> <span class="kwrd">return</span> -1;<br /> }<br /> <span class="rem">/// &lt;summary&gt;</span><br /> <span class="rem">/// Gets list of non-loaded object ids in particular window</span><br /> <span class="rem">/// &lt;/summary&gt;</span><br /> <span class="rem">/// &lt;param name="startingIndex"&gt;&lt;/param&gt;</span><br /> <span class="rem">/// &lt;param name="count"&gt;&lt;/param&gt;</span><br /> <span class="rem">/// &lt;returns&gt;&lt;/returns&gt;</span><br /> <span class="kwrd">public</span> List&lt;<span class="kwrd">object</span>&gt; GetUnloadedIdList(<span class="kwrd">int</span> startingIndex, <span class="kwrd">int</span> count)<br /> {<br /> List&lt;<span class="kwrd">object</span>&gt; idList = <span class="kwrd">new</span> List&lt;<span class="kwrd">object</span>&gt;();<br /> <span class="kwrd">if</span> (startingIndex &gt;= _idList.Count)<br /> <span class="kwrd">return</span> idList;<br /> <span class="kwrd">int</span> endIndex = startingIndex + count;<br /> <span class="kwrd">if</span> (endIndex &gt; _idList.Count)<br /> endIndex = _idList.Count;<br /> IList list = _idList <span class="kwrd">as</span> IList;<br /> <span class="kwrd">for</span> (<span class="kwrd">int</span> i = startingIndex; i &lt; endIndex; i++)<br /> {<br /> ObjectInfo info = list[i] <span class="kwrd">as</span> ObjectInfo;<br /> <span class="kwrd">if</span> (info._loadedObject == <span class="kwrd">null</span>)<br /> idList.Add(info._id);<br /> }<br /> <span class="kwrd">return</span> idList;<br /> }<br /> <span class="rem">/// &lt;summary&gt;</span><br /> <span class="rem">/// Clears everything</span><br /> <span class="rem">/// &lt;/summary&gt;</span><br /> <span class="kwrd">public</span> <span class="kwrd">void</span> Clear()<br /> {<br /> _idList.Clear();<br /> }<br /> <span class="preproc">#endregion</span><br /><br /> <span class="preproc">#region</span> Properties<br /> <span class="rem">/// &lt;summary&gt;</span><br /> <span class="rem">/// Number of ids in the list</span><br /> <span class="rem">/// &lt;/summary&gt;</span><br /> <span class="kwrd">public</span> <span class="kwrd">int</span> Count<br /> {<br /> get { <span class="kwrd">return</span> _idList.Count; }<br /> }<br /><br /> <span class="preproc">#endregion</span><br /><br /> }<br /></pre><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10995029-1027808664791792754?l=discoveringdotnet.alexeyev.org'/></div>Maxim Alexeyevhttp://www.blogger.com/profile/09080974570415524781noreply@blogger.com0tag:blogger.com,1999:blog-10995029.post-75802999365144813782009-01-11T21:40:00.005-05:002009-01-12T00:06:44.059-05:00Lazy loading for CSLA lists to support Server mode in DevExpress Grid. Part 1In one of our WinForms projects, I implemented so-called "lazy loading" for CSLA lists. We were very pleased with the results, so I decided to describe what was done.<br /><br />First, let's state the problem I'm solving. We have classical <span style="font-weight:bold;">client-server</span> (and this is important, to make it work for n-tier, it would need to be modified) application and we want to display list of some objects, let's say customers. The list can be quite long, like 60K records. When I tried to populate that list, it took quite a long time, more than 10 seconds.<br /><br />Now, we used DevExpress grid in our application that supported Server mode. To use this we would have to implement IListServer interface. The version of CSLA we used at the moment was 3.0.3<br /><br />First, to avoid dependencies on user interface logic from my business layer, new interface was introduced, which is copied from IListServer.<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="rem">/// &lt;summary&gt;</span><br /> <span class="rem">/// ILazyLoading interface is needed to support lazy loading, or loading on demand</span><br /> <span class="rem">/// &lt;/summary&gt;</span><br /> <span class="kwrd">public</span> <span class="kwrd">interface</span> ILazyLoading<br /> {<br /> <span class="rem">/// &lt;summary&gt;</span><br /> <span class="rem">/// Number of all object in the list, including not loaded</span><br /> <span class="rem">/// &lt;/summary&gt;</span><br /> <span class="kwrd">int</span> Count { get;}<br /> <br /> <span class="rem">/// &lt;summary&gt;</span><br /> <span class="rem">/// Returns object by index. If object wasn't loaded before, it has to be loaded here</span><br /> <span class="rem">/// &lt;/summary&gt;</span><br /> <span class="rem">/// &lt;param name="index"&gt;&lt;/param&gt;</span><br /> <span class="rem">/// &lt;returns&gt;&lt;/returns&gt;</span><br /> <span class="kwrd">object</span> <span class="kwrd">this</span>[<span class="kwrd">int</span> index] { get; set;}<br /> <span class="rem">/// &lt;summary&gt;</span><br /> <span class="rem">/// Get row index by unique id</span><br /> <span class="rem">/// &lt;/summary&gt;</span><br /> <span class="rem">/// &lt;param name="key"&gt;&lt;/param&gt;</span><br /> <span class="rem">/// &lt;returns&gt;&lt;/returns&gt;</span><br /> <span class="kwrd">int</span> GetRowIndex(<span class="kwrd">object</span> key);<br /> <span class="rem">/// &lt;summary&gt;</span><br /> <span class="rem">/// Get unique id of the row by index</span><br /> <span class="rem">/// &lt;/summary&gt;</span><br /> <span class="rem">/// &lt;param name="index"&gt;&lt;/param&gt;</span><br /> <span class="rem">/// &lt;returns&gt;&lt;/returns&gt;</span><br /> <span class="kwrd">object</span> GetRowKey(<span class="kwrd">int</span> index);<br /> <span class="rem">/// &lt;summary&gt;</span><br /> <span class="rem">/// Add object to list</span><br /> <span class="rem">/// &lt;/summary&gt;</span><br /> <span class="rem">/// &lt;param name="value"&gt;&lt;/param&gt;</span><br /> <span class="rem">/// &lt;returns&gt;&lt;/returns&gt;</span><br /> <span class="kwrd">int</span> Add(<span class="kwrd">object</span> <span class="kwrd">value</span>);<br /> <span class="rem">/// &lt;summary&gt;</span><br /> <span class="rem">/// Clear</span><br /> <span class="rem">/// &lt;/summary&gt;</span><br /> <span class="kwrd">void</span> Clear();<br /> <span class="rem">/// &lt;summary&gt;</span><br /> <span class="rem">/// Contains</span><br /> <span class="rem">/// &lt;/summary&gt;</span><br /> <span class="rem">/// &lt;param name="value"&gt;&lt;/param&gt;</span><br /> <span class="rem">/// &lt;returns&gt;&lt;/returns&gt;</span><br /> <span class="kwrd">bool</span> Contains(<span class="kwrd">object</span> <span class="kwrd">value</span>);<br /> <span class="rem">/// &lt;summary&gt;</span><br /> <span class="rem">/// IndexOf</span><br /> <span class="rem">/// &lt;/summary&gt;</span><br /> <span class="rem">/// &lt;param name="value"&gt;&lt;/param&gt;</span><br /> <span class="rem">/// &lt;returns&gt;&lt;/returns&gt;</span><br /> <span class="kwrd">int</span> IndexOf(<span class="kwrd">object</span> <span class="kwrd">value</span>);<br /> <span class="rem">/// &lt;summary&gt;</span><br /> <span class="rem">/// Insert</span><br /> <span class="rem">/// &lt;/summary&gt;</span><br /> <span class="rem">/// &lt;param name="index"&gt;&lt;/param&gt;</span><br /> <span class="rem">/// &lt;param name="value"&gt;&lt;/param&gt;</span><br /> <span class="kwrd">void</span> Insert(<span class="kwrd">int</span> index, <span class="kwrd">object</span> <span class="kwrd">value</span>);<br /> <span class="rem">/// &lt;summary&gt;</span><br /> <span class="rem">/// Same as IList.IsFixedSize</span><br /> <span class="rem">/// &lt;/summary&gt;</span><br /> <span class="kwrd">bool</span> IsFixedSize { get;}<br /> <span class="rem">/// &lt;summary&gt;</span><br /> <span class="rem">/// Same as IList.IsReadOnly</span><br /> <span class="rem">/// &lt;/summary&gt;</span><br /> <span class="kwrd">bool</span> IsReadOnly { get;}<br /> <span class="rem">/// &lt;summary&gt;</span><br /> <span class="rem">/// Remove</span><br /> <span class="rem">/// &lt;/summary&gt;</span><br /> <span class="rem">/// &lt;param name="value"&gt;&lt;/param&gt;</span><br /> <span class="kwrd">void</span> Remove(<span class="kwrd">object</span> <span class="kwrd">value</span>);<br /> <span class="rem">/// &lt;summary&gt;</span><br /> <span class="rem">/// RemoveAt</span><br /> <span class="rem">/// &lt;/summary&gt;</span><br /> <span class="rem">/// &lt;param name="index"&gt;&lt;/param&gt;</span><br /> <span class="kwrd">void</span> RemoveAt(<span class="kwrd">int</span> index);<br /> <span class="rem">/// &lt;summary&gt;</span><br /> <span class="rem">/// ApplySort</span><br /> <span class="rem">/// &lt;/summary&gt;</span><br /> <span class="rem">/// &lt;param name="sortInfo"&gt;&lt;/param&gt;</span><br /> <span class="kwrd">void</span> ApplySort(ListSortDescriptionCollection sortInfo);<br /> <span class="rem">/// &lt;summary&gt;</span><br /> <span class="rem">/// Same as IBindingList, but need to override it to change indexes</span><br /> <span class="rem">/// &lt;/summary&gt;</span><br /> <span class="kwrd">event</span> ListChangedEventHandler ListChanged;<br /> }<br /></pre><br /><br />The next step is implementing this. There were two ways doing this. One is without modified CSLA library by putting implementation into my base objects. The disadvantage of this approach is that it would require repeating everything for read-only and base lists. So, I decided to not bother with that and put my implementation directly into source code, making it as less intrusive as possible. Which means I modified ExtendedBindingList<T> little bit.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10995029-7580299936514481378?l=discoveringdotnet.alexeyev.org'/></div>Maxim Alexeyevhttp://www.blogger.com/profile/09080974570415524781noreply@blogger.com0tag:blogger.com,1999:blog-10995029.post-79476561212528595002009-01-02T11:09:00.003-05:002009-01-02T11:15:23.091-05:00Linq to SQL performanceThere is a new hype about Linq to SQL now. And honestly, I don't get it. May be I am too old :)<br /><br />Anyway, I would not care about this much if it was just about how you write your code. The problem is that to save few lines of code you loose performance. I wanted to compare how much is lost when I found that someone already did it <a href="http://agilior.pt/blogs/pedro.rainho/archive/2008/07/11/5007.aspx">here</a>.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10995029-7947656121252859500?l=discoveringdotnet.alexeyev.org'/></div>Maxim Alexeyevhttp://www.blogger.com/profile/09080974570415524781noreply@blogger.com2tag:blogger.com,1999:blog-10995029.post-23316941113223102412008-12-24T18:17:00.002-05:002008-12-24T18:27:02.028-05:00Sorting in WPF DataGridAs you could see from my previous post, I am using WPF Toolkit DataGrid now. One of the reason to do it is to sort data. Sure, it is possible to do sorting in ListView, but using DataGrid I can do it with less efforts.<br /><br />The only problem was that what I had as data source was regular BindingList, that does not support sorting. So, sorting just didn't work.<br /><br />The solution I found the easiest is using Linq. Since I assigned my data source in code, not XAML, there was no inconvenience at all.<br /><br />Instead of line<br /><pre class="csharpcode"><br />ItemsSource = list</pre><br /><br />I used<br /><br /><pre class="csharpcode"><br />ItemsSource = from item <span class="kwrd">in</span> list select item;</pre><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10995029-2331694111322310241?l=discoveringdotnet.alexeyev.org'/></div>Maxim Alexeyevhttp://www.blogger.com/profile/09080974570415524781noreply@blogger.com0tag:blogger.com,1999:blog-10995029.post-2258030802141525792008-12-11T23:21:00.008-05:002008-12-24T18:27:02.029-05:00Changing background color for header in WPF Toolkit DataGridToday I decided to look at DataGrid from <a href="http://www.codeplex.com/wpf/Release/ProjectReleases.aspx">WPF Toolkit</a>, available at CodePlex. As you may expect, the first thing I needed to do is to change it look. I started from changing background and immediately stuck.<br /><br />1. Changed Background - didn't work for everything<br />2. Changed RowBackground - still not everything.<br />3. And then I added style for DataGridColumnHeader - now I had geader, but still some small rectungles remained gray.<br />4. And then something strange happened, I added style for DataGridRowHeader with yellow background, but result was completely unexpected. I got what I wanted, but I still don't understand how.<br /><br />Here is my result.<br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">&lt;</span><span class="html">dg:DataGrid</span> <span class="attr">x:Name</span><span class="kwrd">="grid"</span> <span class="attr">Background</span><span class="kwrd">="Red"</span> <span class="attr">RowBackground</span><span class="kwrd">="Red"</span> <span class="attr">IsReadOnly</span><span class="kwrd">="True"</span> <span class="attr">GridLinesVisibility</span><span class="kwrd">="None"</span> <span class="kwrd">&gt;</span><br /> <span class="kwrd">&lt;</span><span class="html">dg:DataGrid.Resources</span><span class="kwrd">&gt;</span><br /> <span class="kwrd">&lt;</span><span class="html">Style</span> <span class="attr">TargetType</span><span class="kwrd">="{x:Type dgp:DataGridColumnHeader}"</span><span class="kwrd">&gt;</span><br /> <span class="kwrd">&lt;</span><span class="html">Setter</span> <span class="attr">Property</span><span class="kwrd">="Background"</span> <span class="attr">Value</span><span class="kwrd">="Red"</span><span class="kwrd">/&gt;</span><br /> <span class="kwrd">&lt;/</span><span class="html">Style</span><span class="kwrd">&gt;</span><br /> <span class="kwrd">&lt;</span><span class="html">Style</span> <span class="attr">TargetType</span><span class="kwrd">="{x:Type dgp:DataGridRowHeader}"</span><span class="kwrd">&gt;</span><br /> <span class="kwrd">&lt;</span><span class="html">Setter</span> <span class="attr">Property</span><span class="kwrd">="Background"</span> <span class="attr">Value</span><span class="kwrd">="Green"</span><span class="kwrd">/&gt;</span><br /> <span class="kwrd">&lt;/</span><span class="html">Style</span><span class="kwrd">&gt;</span><br /> <span class="kwrd">&lt;/</span><span class="html">dg:DataGrid.Resources</span><span class="kwrd">&gt;</span><br /> <span class="kwrd">&lt;</span><span class="html">dg:DataGrid.Columns</span><span class="kwrd">&gt;</span><br /> <span class="kwrd">&lt;</span><span class="html">dg:DataGridTextColumn</span> <span class="attr">Header</span><span class="kwrd">="Test column"</span><span class="kwrd">/&gt;</span><br /> <span class="kwrd">&lt;/</span><span class="html">dg:DataGrid.Columns</span><span class="kwrd">&gt;</span><br /> <span class="kwrd">&lt;/</span><span class="html">dg:DataGrid</span><span class="kwrd">&gt;</span><br /></pre><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10995029-225803080214152579?l=discoveringdotnet.alexeyev.org'/></div>Maxim Alexeyevhttp://www.blogger.com/profile/09080974570415524781noreply@blogger.com0tag:blogger.com,1999:blog-10995029.post-43685280525346939792008-10-17T23:40:00.002-04:002008-10-17T23:45:31.379-04:00Variable number of parameters in C#I wish I knew it before, it would save me few hours (don't ask me why).<br /><br />Apparently it is possible to make variable number of parameters in method using keyword <a href="http://msdn.microsoft.com/en-us/library/w5zay9db%28VS.71%29.aspx">params</a>.<br /><br />There are obvious limitations, it can be only the last parameters of the same time. But nevertheless, I think it's cool.<br /><br />There is positive result for me not knowing that. Now I finally figured out how to work with regular expression, see Regex class. This is really powerful tool to have too.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10995029-4368528052534693979?l=discoveringdotnet.alexeyev.org'/></div>Maxim Alexeyevhttp://www.blogger.com/profile/09080974570415524781noreply@blogger.com1tag:blogger.com,1999:blog-10995029.post-32123926375630005902008-09-19T23:44:00.003-04:002008-09-19T23:55:34.882-04:00ComboBox - DisplayMemberPath or TextSearch.TextPathProbably it's just too late already, and I am slow, but I was confused with DisplayMemberPath and TextSearch.TextPath properties.<br /><br />First, I added some objects to ComobBox.Items. Not using XML, I did it dynamically from C#. It worked find on Vista computer, but then it didn't work under XP. I just got empty values instead of value of ToString() method.<br /><br />OK, I looked in my favorite book <a href="http://discoveringdotnet.alexeyev.org/2007/10/books.html">WPF Unleashed</a>, and found that TextSearch.TextPath should be used. Well, it didn't help. It took me a while until I got to try old familiar DisplayMemberPath property and then it worked.<br /><br />So, the question I have now is why TextSearch.TextPath didn't work? Or if asked in more general way, what are the rules. When I am supposed to use DisplayMemberPath and when TextSearch.TextPath. Anybody?<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10995029-3212392637563000590?l=discoveringdotnet.alexeyev.org'/></div>Maxim Alexeyevhttp://www.blogger.com/profile/09080974570415524781noreply@blogger.com3tag:blogger.com,1999:blog-10995029.post-20988581079874240872008-09-10T00:08:00.003-04:002008-09-10T13:59:13.288-04:00Hyperlinks in WPF ContinuedI <a href="http://discoveringdotnet.alexeyev.org/2008/08/there-is-no-linkcontrol-in-wpf-so-if.html">wrote before</a> about using hyperlinks in WPF. For my new <a href="http://urbandictionary.alexeyev.org/">side project</a> I need to switch from hypertext to the simple text depending on availability of URL. Switching to simple text seemed easy, just assigning text value to the Text property worked. Switching back was not obvious for me.<br /><br />Then I found that TextBlock has Inlines property. The code became this:<br /><br /><div style="text-align: left;font-family:courier new;"> tHypertext.Inlines.Clear();<br /> if (!string.IsNullOrEmpty(uri))<br /> {<br /> if (!string.IsNullOrEmpty(value))<br /> tHypertext.Inlines.Add(value);<br /> tHypertext.NavigateUri = new Uri(uri);<br /> tTextBlock.Inlines.Clear();<br /> tTextBlock.Inlines.Add(tWord);<br /> }<br /> else<br /> {<br /> tTextBlock.Text = value;<br /> tHypertext.NavigateUri = null;<br /> }<br /><br /><span style="font-family:arial;">Where TextBlock and Hypertext are from previouse example</span><br /></div><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10995029-2098858107987424087?l=discoveringdotnet.alexeyev.org'/></div>Maxim Alexeyevhttp://www.blogger.com/profile/09080974570415524781noreply@blogger.com0tag:blogger.com,1999:blog-10995029.post-49935788892083399632008-09-04T23:48:00.002-04:002008-09-04T23:52:58.538-04:00Keyboard.Modifiers sometimes doesn't workThere are many examples how to implement keyboard hooks in .NET. The one I used as example is <a href="http://blogs.vertigo.com/personal/ralph/Blog/archive/2007/02/12/wpf-low-level-keyboard-hook-sample.aspx">http://blogs.vertigo.com/personal/ralph/Blog/archive/2007/02/12/wpf-low-level-keyboard-hook-sample.aspx</a><br /><br />There is very important comment there that says Keyboard.Modifier property does not return correct values. First, I wanted to avoid linking to <span style="font-family: courier new;">System.Windows.Form</span> assembly and didn't pay much attention go this comments. Well, it didn't work. I had come back to using <span style="font-family: courier new;">System.Windows.Forms.Control.ModifierKeys</span>. To make interface more WPF compatible I just converted value this way:<br /><br /><span style="font-family: courier new;"> System.Windows.Forms.Keys m = System.Windows.Forms.Control.ModifierKeys;</span><br /><span style="font-family: courier new;"> ModifierKeys m2 = ModifierKeys.None;</span><br /><span style="font-family: courier new;"> if ((m &amp; System.Windows.Forms.Keys.Control) != 0)</span><br /><span style="font-family: courier new;"> m2 = m2 | ModifierKeys.Control;</span><br /><span style="font-family: courier new;"> if ((m &amp; System.Windows.Forms.Keys.Alt) != 0)</span><br /><span style="font-family: courier new;"> m2 = m2 | ModifierKeys.Alt;</span><br /><span style="font-family: courier new;"> if ((m &amp; System.Windows.Forms.Keys.Shift) != 0)</span><br /><span style="font-family: courier new;"> m2 = m2 | ModifierKeys.Shift;</span><br /><span style="font-family: courier new;"> if ((m &amp; System.Windows.Forms.Keys.Apps) != 0)</span><br /><span style="font-family: courier new;"> m2 = m2 | ModifierKeys.Windows;</span><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10995029-4993578889208339963?l=discoveringdotnet.alexeyev.org'/></div>Maxim Alexeyevhttp://www.blogger.com/profile/09080974570415524781noreply@blogger.com0tag:blogger.com,1999:blog-10995029.post-45529940111267446222008-08-20T23:07:00.004-04:002009-01-12T13:52:35.646-05:00SystemEvents.PowerModeChanged Event and servicesAs I posted <a href="http://discoveringdotnet.alexeyev.org/2008/02/sens-events.html">before</a> I wrote small <a href="http://counttime.alexeyev.org/">application</a> to know how much time my daughter logged on computer. To do this I used SENS events. And then I noticed that numbers are to big. And the problem was that these events did not trigger when computer went to sleep or hibernate modes. And service did not stop either. .NET has <span style="font-weight: bold;">SystemEvents.PowerModeChanged</span> event that I decided to use. Surprise, it doesn't work from service. The solution was found in <span style="font-weight: bold;">System.Management</span> name space and <span style="font-weight: bold;">ManagementEventWatcher</span> class.<br /><br />Here is the fragment of the code I used:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br />WqlEventQuery query = <span class="kwrd">new</span> WqlEventQuery(<span class="str">"Win32_PowerManagementEvent"</span>);<br />_watcher = <span class="kwrd">new</span> ManagementEventWatcher(query);<br />_watcher.EventArrived += <span class="kwrd">new</span> EventArrivedEventHandler(watcher_EventArrived);<br />_watcher.Start();</pre><br /></span><br />when my service started.<br /><br /><span style="font-size:85%;"><span style="font-family:courier new;">_watcher.Stop();</span><br /></span><br />when it stopped.<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /><span class="kwrd">void</span> watcher_EventArrived(<span class="kwrd">object</span> sender, EventArrivedEventArgs e)<br /> {<br /> <span class="kwrd">try</span><br /> {<br /> <span class="kwrd">int</span> eventType = Convert.ToInt32(e.NewEvent.Properties[<span class="str">"EventType"</span>].Value);<br /> <span class="kwrd">switch</span> (eventType)<br /> {<br /> <span class="kwrd">case</span> 4:<br /> Sleep();<br /> <span class="kwrd">break</span>;<br /> <span class="kwrd">case</span> 7:<br /> Resume();<br /> <span class="kwrd">break</span>;<br /> }<br /> }<br /> <span class="kwrd">catch</span> (Exception ex)<br /> {<br /> Log(ex.Message);<br /> }<br /> }<br /></pre><br /><br />- event handler.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10995029-4552994011126744622?l=discoveringdotnet.alexeyev.org'/></div>Maxim Alexeyevhttp://www.blogger.com/profile/09080974570415524781noreply@blogger.com0tag:blogger.com,1999:blog-10995029.post-35689522391483567882008-08-17T00:53:00.003-04:002008-08-17T01:01:04.504-04:00InkEdit does not work when there are no recognition package for your languageIt was a midnight when I got pinged by my boss from Mexico. The Ink control that we inserted into our application didn't work. And we used InkEdit.<br /><br />It was tested before, everything worked fine, there were no recent changes that could break it, and I didn't have Tablet PC at home to duplicate it. We had terminal session and I just couldn't get it. It worked before.<br /><br />Finally, we realized that standard pop up control (with virtual keyboard) didn't work either. And then we noticed that current language was Spanish, and then we switched to English and everything worked.<br /><br />So, what they (customer) did - they changed default keyboard input to Spanish, and InkEdit stopped working. Which makes some sense, InkEdit supposed to be used to recognize what you entered, not just store pictures. If you need just store everything was scrubbled without attempting to recognize it, InkPicture should be used.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10995029-3568952239148356788?l=discoveringdotnet.alexeyev.org'/></div>Maxim Alexeyevhttp://www.blogger.com/profile/09080974570415524781noreply@blogger.com0tag:blogger.com,1999:blog-10995029.post-55471528807614255182008-08-17T00:41:00.003-04:002008-08-17T00:52:31.164-04:00Getting File size using ContentLength when downloading from FTP serverThere is a property <a href="http://msdn.microsoft.com/en-us/library/system.net.ftpwebresponse.contentlength.aspx">ContentLength </a>of class FtpWebResponse. When I wrote the code similar to example, provided by MSDN, this property always returned -1. As it turned out, it was important to read fine print. I had to set method to GetFileSize to get proper value. So, what I got in result that worked was this:<br /><br /><span style="font-family: courier new;"> // Get file size</span><br /><span style="font-family: courier new;"> FtpWebRequest request = (FtpWebRequest)WebRequest.Create(_uri);</span><br /><span style="font-family: courier new;"> request.Method = WebRequestMethods.Ftp.GetFileSize;</span><br /><span style="font-family: courier new;"> request.Credentials = credential;</span><br /><span style="font-family: courier new;"> FtpWebResponse response = (FtpWebResponse)request.GetResponse();</span><br /><span style="font-family: courier new;"> long fileSize = response.ContentLength;</span><br /><br /><span style="font-family: courier new;"> // Download file</span><br /><span style="font-family: courier new;"> request = (FtpWebRequest)WebRequest.Create(_uri);</span><br /><span style="font-family: courier new;"> request.Method = WebRequestMethods.Ftp.DownloadFile;</span><br /><span style="font-family: courier new;"> request.Credentials = credential;</span><br /><span style="font-family: courier new;"> response = (FtpWebResponse)request.GetResponse();</span><br /><br /><br />And then getting stream from response etc.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10995029-5547152880761425518?l=discoveringdotnet.alexeyev.org'/></div>Maxim Alexeyevhttp://www.blogger.com/profile/09080974570415524781noreply@blogger.com1