giovedì 21 febbraio 2013

Quando un distinct non basta. Linq workaround


Ci troviamo spesso nella situazione di dover effettuare dei distinct di oggetti di una collection di cui ci interessa che il distinct effettuato riguardi un sottogruppo di campi. Capita anche, lavorando con iQuerable provenienti da un orm interfacciato con un database quali EntityFramework o Linq-To-Sql classes, che le entità in oggetto in realtà comprendano dei campi scritti da trigger database che non ci interessano particolarmente. Oltre all'iterazione dell'intera collection o dell'intero iQuerable (che tra l'altro causa la materializzazione in ram di ogni singola entità iterata con conseguente aumento del costo computazionale) una soluzione relativamente standard consiste nel creare un'implementazione di IEqualityComparer per la classe specifica delle entità in considerazione.


How To: Lambda Distinct.

Ammetto che la soluzione non è assolutamente mia, ma di un nuovo editor che a breve potrà partecipare al Blog.. ben venuto Vittorio.

Il dilemma del giorno è come ottenere l'effetto del distinct SQL tramite lambda...


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace IQuerableDistinct
{
    public class friend
    {
        public string Surname { get; set; }
        public string Name { get; set; }
        public string Nick { get; set; }
        public string Socialpage { get; set; }
    }

    public class friends : List<friend> { };

    class Program
    {
        static void Main(string[] args)
        {

            friend f = new friend() 
                { Surname = "Arosio", 
                  Name = "Fabio", 
                  Nick = "thema!", 
                  Socialpage="" };
            
            friend f1 = new friend() 
                { Surname = "Arosio", 
                  Name = "Fabio", 
                  Nick = "nudrubufu", 
                  Socialpage = "nudrubufu.blogspot.com" };

            friend f2 = new friend() 
                { Surname = "Arosio", 
                  Name = "Fabio", 
                  Nick = "xa", 
                  Socialpage = "deviantArt.com/Thema" };

            friend f3 = new friend() 
                { Surname = "Arosio", 
                  Name = "Fabio", 
                  Nick = "TheMa!", 
                  Socialpage = "flikr.com/213445" };

            friend f4 = new friend() 
                { Surname = "Arosio", 
                  Name = "Fabio", 
                  Nick = "TheMa!", 
                  Socialpage = "500px/FabioArosio" };


            friends fx = new friends();
            fx.Add(f);
            fx.Add(f1);
            fx.Add(f2);
            fx.Add(f3);
            fx.Add(f4);

            foreach (friend x in fx) 
            { 
                Console.WriteLine(x.Surname + 
                        "\t" + x.Name + 
                        "\t" + x.Nick); 
            }

            Console.WriteLine("\r\nDistinct by Surname+Name...");

            var d = fx.GroupBy(c => c.Surname + c.Name).Select(g => g.First());


            foreach (friend x in d)
            {
                Console.WriteLine(x.Surname +
                        "\t" + x.Name );
            }

            Console.ReadLine();
        }
    }
}

Sembra facile ma non è difficile come al solito.

Creaiamo 4 entità che per comodo e per gestire il nostro esempio presentano valori simili... ma differenti per attributi..

La distinct ci permette di comprendere quanti amici abbiamo con lo stesso nome..

mercoledì 13 febbraio 2013

How to: GroupBox Add Style C# r2

Ed eccomi ancora.. Sapevo che ci sarei cascato in qualche modo..
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;

using System.Windows.Forms;

namespace ColredPanel
{
    public partial class ColoredGroupBox : Panel
    {
        Color _c = Color.Lime;
        Pen _p = null;
        Pen _ps = null;
        bool _s = false;
        int _r = 20;

        public Color GetBoxborder
        {
            get { return _c;}
            set
            {
                _c = value;
                _p = new Pen(new SolidBrush(_c));
                _ps = new Pen(
                        new SolidBrush(Color.WhiteSmoke)
                        );
                this.Refresh();
            }
        }

        public int Radius
        {
            get { return _r; }
            set { _r = value; if (_r > 20) _r = 20; }
        }

        public bool DrawShaodows
        {
            get { return _s; }
            set { _s = value; }
        }

        public string Caption
        {
            get { return lblCaption.Text; }
            set { lblCaption.Text = value; this.Refresh(); }
        }

        public Color CaptionColor
        {
            get { return lblCaption.ForeColor; }
            set { lblCaption.ForeColor = value; }
        }

        public ColoredGroupBox()
        {
            InitializeComponent();
            _p = new Pen(new SolidBrush(_c));          
        }


        private void ColoredGroupBox_Paint(object sender, 
                PaintEventArgs e)
        {       
            RounderedSchema(e.Graphics);
        }


        private void RounderedSchema(Graphics g)
        {
            g.CompositingQuality = 
                    System.Drawing.Drawing2D.CompositingQuality.HighQuality;

            g.FillRectangle(new SolidBrush(this.BackColor)
                    ,0, 0, this.Width, this.Height);

            _p.Width = 1f;
            g.DrawArc(_p, 10, 10, _r, _r, 180, 90);
            g.DrawLine(_p, 18, 10, this.Width - 13, 10);
            g.DrawArc(_p, 10, this.Height - 25, _r, _r, 180, -90);
            g.DrawArc(_p, this.Width - 25, this.Height - 25, _r, _r, 0, 90);
            g.DrawLine(_p, 10, 18, 10, this.Height - 13);
            g.DrawArc(_p, this.Width -25, 10, _r, _r, 0,-90);
            g.DrawLine(_p, 18, this.Height - 5, this.Width - 13, this.Height - 5);
            g.DrawLine(_p, this.Width - 5, 18, this.Width -5, this.Height - 13);

          
            if (_s)
            {
                g.DrawLine(_ps, 18, 11, this.Width - 13, 11);
                g.DrawLine(_ps, 11, 18, 11, this.Height - 13);
            }

            g.FillEllipse(new SolidBrush(_c), 25, 3, _r - 2, _r - 2);
            g.FillEllipse(new SolidBrush(_c), lblCaption.Width +50 , 3, _r - 2, _r - 2);
            g.FillRectangle(new SolidBrush(_c), 35, 4, lblCaption.Width + 25, _r-3);
        }

        private void ColoredGroupBox_Resize(object sender, EventArgs e)
        {
            if (this.Handle != null)
            {
                RounderedSchema(Graphics.FromHwnd(this.Handle));
            }
        }
    }
}
Questa versione è come la precedente solo che è migliore.. ed è più stabile e funziona un po meglio.

martedì 12 febbraio 2013

How to: GroupBox Add Style C#

Facile .. non si può, se lavorate in window form.
L'unica è usare wpf .. ma non è detta l'ultima parola, ossia se proprio siete ostinati e non volete scaricarvi la libreria di qualcuno che non conoscete, l'unica è farvelo da voi.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;

using System.Windows.Forms;

namespace ColredPanel
{
    public partial class ColoredGroupBox : UserControl
    {
        Color _c = Color.Lime;
        Pen _p = null;

        public Color GetBoxborder
        {
            get { return _c;}
            set
            {
                _c = value;
                _p = new Pen(new SolidBrush(_c));
                lblCaption.BackColor = _c;
            }
        }

        public string Caption
        {
            get { return lblCaption.Text; }
            set { lblCaption.Text = value; }
        }


        public ColoredGroupBox()
        {
            InitializeComponent();
            _p = new Pen(new SolidBrush(_c));

        }


        private void ColoredGroupBox_Paint
                   (object sender, PaintEventArgs e)
        {

            _p.Width = 2;
            
            e.Graphics.FillRectangle(
                     new SolidBrush(_c), 30, 4, lblCaption.Width, 19);

            e.Graphics.DrawEllipse(_p, 22, 5, 16, 16);
            e.Graphics.FillEllipse(new SolidBrush(_c), 21, 5, 16, 16);
            e.Graphics.DrawEllipse(_p, 20+lblCaption.Width, 5, 16, 16);            
            e.Graphics.FillEllipse(new SolidBrush(_c), 20 + lblCaption.Width,
               5, 16, 16);

                       
            e.Graphics.DrawRectangle(_p, 13, 13, this.Width - 20, 
               this.Height - 20);            
        }
    }
}

Questo naturalmente si tratta di un esempio .. che non è del tutto calzante perchè a design time il controllo fa davvero schifo.

Ma dato che si tratta di un esempio lascio a voi tutta la creatività che può servirvi per rendere il vostro controllo il più bello e lento possibile..



mercoledì 6 febbraio 2013

UpdatePanel never Update.

Questo problema ammetto che mi ha causato davvero un tremendo malessere.

<asp:Timer ID="tmrSplineChart" runat="server" 
        ontick="tmrSplineChart_Tick" 
        Interval="25000">
</asp:Timer>                                
<asp:UpdatePanel ID="updChart" 
            runat="server" 
            UpdateMode="Conditional" 
            ChildrenAsTriggers="false">
    <Triggers>
        <asp:AsyncPostBackTrigger 
                ControlID="tmrSplineChart" 
                EventName="Tick" />
    </Triggers>                    
    <ContentTemplate>                       
       <%Response.Write (DateTime.Now.ToLongTimestring());%>
    </ContentTemplate>
 </asp:UpdatePanel>

Risultato: Non aggiorna .. PERCHE'?

Se provate a vedere la pagina con firebug (per esempio) attivando la console scoprirete che il comando Response.Write ( ... ) è causa di un errore.

E non solo blocca completamente tutto quello che avviene nell'update panel ( prima o dopo ), in breve ( dopo aver generato un errore )  inibisce il rendering del content template.

Come lo si risolve?

Ci sono vari metodi, il primo è di utilizzare controlli specifci come label textbox e simili.

E se ci fosse un qualcosa di più complesso ? Come ad esempio registrare un script da eseguire in client side ?


public void UpdateData()
{
    lblDate.Text = "Last Update: " + DateTime.Now.ToLongTimeString();

    string s = @"
                $(document).ready(function() {
                    
                    alert (" Eccomi !");

                    });   
                 ";



    ScriptManager.RegisterClientScriptBlock(
        this.Page, 
        this.Page.GetType(), 
        "Alert_Eccomi", s, true);
}

Il mio consiglio e di utilizzare lo ScritpManager  ( classe statica presente nell'oggetto Page ), che è ne più ne meno lo ScriptManager Ajax.

In questo modo lo script sarà "implementato nella pagina e gestito" senza troppe complicazioni.

Jquery ( come da esempio ) funziona !