Καλώς ορίσατε στο dotNETZone.gr - Σύνδεση | Εγγραφή | Βοήθεια

CodeColorizer: Ενα plugin για χρωματιστό κώδικα στο Windows Live Writer

Οταν χρησιμοποιείτε το Windows Live Writer, δεν έχετε τη δυνατότητα by default να τοποθετήσετε έγχρωμο και σωστά idented κώδικα στα posts σας. Κατεβάζοντας ένα Live Writer plugin από αυτή τη διεύθυνση: http://www.carlosag.net/Tools/WindowsLiveWriter/, το πρόβλημα λύνεται!

Το χρησιμοποίησα και έμεινα απόλυτα ικανοποιημένος. Οδηγίες για την εγκατάσταση θα βρείτε στην σελίδα που παραπέμπει το link.

Δημοσιεύτηκε στις από το μέλος cap | 0 σχόλια
Δημοσίευση στην κατηγορία:

FriendFeed: Ενα RSS feed για όλες σας τις δραστηριότητες

Ειναι αλήθεια οτι αν πάτε στο FriendFeed δεν θα δείτε κάποιο wow site με όμορφα γραφικά και ελκυστικά τσιτάτα. Ομως, αυτό που κανει είναι πραγματικά χρήσιμο.

Εν ολίγοις: Εγγράφεστε στο FriendFeed, του λέτε ποιά blogs έχετε, και σε ποιές υπηρεσίες είστε εγγεγραμμένοι (π.χ. youtube, del.icio.us, last.fm και άλλες δημοφιλείς υπηρεσίες) και το FriendFeed φροντίζει να παράγει ένα feed με όλες σας τις δραστηριότητες συγκεντρωτικά. Ετσι, έχετε ένα feed που περιέχει τα πάντα για σάς: Από το νέο σας blog post (το FriendFeed τελευταία βελτιώθηκε ωστε να υποστηρίζει πολλαπλά blogs) ως το τελευταίο video που ορίσατε αγαπημένο στο YouTube ή το τελευταίο link που προσθέσατε στο Del.Icio.Us.

Το FriendFeed διαθέτει ένα ολοκληρωμένο API για την ενσωμάτωσή του σε τρίτες εφαρμογές. Ηδη έχει υλοποιηθεί ως Facebook application.

Δείτε το δικό μου feed εδώ: http://www.friendfeed.com/sfilip

 

Δημοσιεύτηκε στις από το μέλος cap | 1 σχόλια
Δημοσίευση στην κατηγορία:

Company Profiles στο LinkedIn

Παρά το οτι πιό "χαλαρά" social networks όπως το Facebook, το MySpace ή το Hi5 κερδίζουν κόσμο από την Ελλάδα, το LinkedIn παραμένει μια σταθερή αξία για την επαγγελματική μας δικτύωση. Ενα profile σας στο LinkedIn μπορεί, ορισμένες φορές, να υποκασταστήσει αποτελεσματικά το κλασικό Word/PDF CV σας, ιδίως αν σε αυτό περιλαμβάνονται συστάσεις από άλλους συνεργάτες.

Ως μεμονωμένος επαγγελματίας, μπορούσε κανείς να κάνει πολλά. Αυτό όμως που έλειπε από το LinkedIn μέχρι σήμερα ήταν τα Company Profiles, σελίδες δηλαδή που περιέχουν στοιχεία για την εταιρία σας, καθώς και τα μέλη του LinkedIn που εργάζονται σε αυτή. Οι πληροφορίες παρέχονται σε συνεργασία με την Capital IQ, που σημαίνει οτι (τουλάχιστον για την beta φάση) θα πρέπει να ξεχάσετε τη δυνατότητα να προσθέσετε τη δική σας εταιρία.

Στα Company Profiles εμφανίζονται ενδιαφέροντα στοιχεία όπως πρόσφατες προσλήψεις, σχετικές εταιριες, προαγωγές, δημοφιλή προφιλ εργαζομένων και άλλα. Το LinkedIn σκοπεύει να κάνει τα Profiles κάτι σαν Wiki, επιτρέποντας στους εργαζόμενους των εταιριών να μεταβάλλουν τα στοιχεία τους.

Η βάση δεδομένων της Capital IQ περιέχει 160.000 εταιρίες, ενώ το LinkedIn σκοπεύει να φτάσει το 1.000.000 Company Profiles στο μέλλον.

Ακούγεται ενδιαφέρον, αρκεί να δοθεί συνεχεια και να επιτραπεί η δημιουργία Company Profiles από τους χρήστες.

Σχετικό υλικό μπορείτε να βρείτε στο LinkedIn Blog.

Αν δεν ξέρετε τι είναι το LinkedIn, μπορείτε να διαβάσετε αυτό το Blog Post: LinkedIn: Η άλλη διάσταση στις επαγγελματικές σχέσεις.

 

 

 

Δημοσιεύτηκε στις από το μέλος cap | 0 σχόλια
Δημοσίευση στην κατηγορία:

Κυκλοφόρησε το DotNetNuke 4.8.1 Language Pack

Κυκλοφόρησε το ενημερωμένο Greek Language Pack για την έκδοση 4.8.1 του DotNetNuke, το οποίο μπορείτε να βρείτε εδώ. Για άλλη μια φορά, όπως και με το προηγούμενο Greek Language Pack, τα ευχαριστήριά σας προς τον κ. Αγγελο Ξυπολιά και την Xelixis.

 

Δημοσιεύτηκε στις από το μέλος cap | 3 σχόλια
Δημοσίευση στην κατηγορία:

Τεχνική παρουσίαση DotNetNuke Portal: Chios Echo

Το http://www.chios-echo.gr/ δημιουργήθηκε φέτος σε συνεργασία με την εταιρία Tool, και φιλοξενείται με τη συνεργασία της εταιρίας Xelixis. Αποσκοπώ και πάλι στο να δώσω μια περιγραφή του από τεχνική σκοπιά.

Το portal τρέχει στην έκδοση 4.8.0 του DotNetNuke και για τη δημιουργία του χρησιμοποιήθηκε προδιαμορφωμένο περιβάλλον ("κομμένα" γραφικά σε HTML) το οποίο μετεξελίχθηκε σε skin. Απαραίτητες ήταν όμως και κάποιες "βαθύτερες" αλλαγές (εκτός του φακέλου /portals), όπως το customization του search box και της σελίδας αποτελεσμάτων αναζήτησης καθώς και κάποια άλλα customizations που αφορούσαν κυρίως τη λειτουργία του navigation side menu ως skin object (βλ. παρακάτω). Για την πρώτη σελίδα χρησιμοποιείται διαφορετικό ascx αρχείο (διπλό content pane) από ο,τι για τις εσωτερικές.

Το top-level navigation είναι "καρφωτό" με τα γνωστά javascripts για το onMouseOver image roll, δεδομένου οτι τα top-level links δεν μεταβάλλονται. Αν και θα μπορούσε να χρησιμοποιηθεί κάποιο module, δεν υπήρχε ουσιαστικά κάποιο μεγαλύτερο πρακτικό όφελος.

Για την ενοτητα των νέων χρησιμοποιήθηκε το module Orizonti NukeNews, κατάλληλα προσαρμοσμένο. Υπήρχε όμως η απαίτηση στην πρώτη σελίδα να εμφανίζεται ένα top x των ειδήσεων. Δεδομένου οτι το NukeNews module δεν παρείχε αυτή τη λειτουργικότητα, για αυτή την απαίτηση χρησιμοποιήθηκε το ListX module, το οποίο επιτρέπει απευθείας queries στην database και συγκεκριμένα στα database tables του NukeNews module, και ενεργοποιήθηκε για αυτό η λειτουργία Ajax έτσι ωστε ο χρήστης να μην περιμένει τη φόρτωση των τίτλων για να δει την πρώτη σελίδα.

Για το side navigation χρησιμοποιήθηκε (με αρκετά μεγάλη προσαρμογή) το CISS.SideMenu module,το οποίο αποτελεί μέρος του πακέτου Navigation Suite All-in-one. Το module χρησιμοποιήθηκε ως skin object. Το ίδιο ακριβώς module, με διαφορετικό configuration και styling αυτή τη φορά, χρησιμοποιήθηκε και για την δημιουργία του sitemap του portal.

Για την παροχή στοιχείων στην υπηρεσία Google Analytics χρησιμοποιήθηκε το δωρεάν SVS Google Analytics module.

Τελος, από τα core modules έχει γίνει χρήση του core DNN Repository module για την παροχή εγγράφων και ακουστικού υλικού προς λήψη, του FAQ module για την παροχή FAQs (τι άλλο; :) ), ενώ μελλοντικά θα χρησιμοποιηθεί και το DNN Forum core module.

Το portal βρίσκεται υπό ανάπτυξη, και ενδέχεται να προστεθούν και άλλα modules στο άμεσο μέλλον για να καλυφθούν οι επιπρόσθετες απαιτήσεις λειτουργικότητας.

 

 

Δημοσιεύτηκε στις από το μέλος cap | 0 σχόλια
Δημοσίευση στην κατηγορία:

Δωρεάν εργαλείο δημιουργίας διαγραμμάτων UML για το Visual Studio

Από το digitalnews.gr διάβασα την πολύ ενδιαφέρουσα είδηση της κυκλοφορίας ενός δωρεάν εργαλείου UML modeling από την Tangible που προστίθεται ως add-on στο Visual Studio επιτρέποντάς σας να ενσωματώσετε στα projects σας διαγράμματα UML και συγκεκριμένα τα εξής:

- Use Case Diagrams
- Component Diagrams
- State Charts
- Class Diagrams
- Activity Diagrams
- Persistent Object Models.

Περισσότερα θα βρείτε εδώ: http://www.tangiblearchitect.net/modellingtools.html

 

Δημοσιεύτηκε στις από το μέλος cap | 0 σχόλια
Δημοσίευση στην κατηγορία: ,

Dynamically adding controls to ASPX pages (web forms) and assigning event handlers

Although I've seen a lot of articles describing how to dynamically add controls to a Web Form, few mention even a little hint to how you can make event handlers actually WORK with dynamically-added controls. This article may seem (and probably is) a beginner-level one, but I think it's essential to cover this issue.

There are a lot of reasons why you would want to dynamically generate Web Forms, i.e. add controls at runtime. Suppose your form's structure depends on metadata stored in a database, or has to change depending on what data it has to do with every time. Whatever the reason, you probably need to dynamically add controls to it like a textbox or two, or even your own complex, fully functional user controls.

How do you do that?

First, let's understand the various ways we can add controls to a web form. We can do it in either of three ways:

1. Declaratively (at design time)
2. Programmatically (at design time)
3. Dynamically (at run-time)

The first two ways are simple: Either we do a declaration somewhere and let VS.NET write the code for us (1), or we just type our own code, including the designer code (2). Both are done in design time. What we are interested in is (3): Doing it at run time.

(We'll be using the Page_Load sub for all our examples, although it's not always the most convenient place to put dynamic control code - just for the sake of simplicity)

The WRONG way

That's what people usually do:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Public Partial Class WebForm1
Inherits System.Web.UI.Page

Protected WithEvents _tx As TextBox

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
_tx = New TextBox
_tx.ID = "textbox1"
Form.Controls.Add(_tx)
End Sub


Private Sub _tx_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles _tx.TextChanged
'do something
End Sub
End Class

This works well if we have only ONE textbox. In order to handle events with the _tx_TextChanged sub which uses the HANDLES keyword, we had to declare our _tx variable as at least visible from everywhere from our page and use the keyword "withevents". We also have to declare an event handling method using the keyword "handles".

What happens, though, if we have to dynamically add an unknown number of textboxes? A number that might change with each run because it depends on some external factor like query results from a database?

Well, the answer is that we can thoretically do that in the way mentioned above, but good-bye event handling. We can set _txt to another new textbox and add that as well to our controls collection. BUT! The _tx_TextChanged event handler will be working only for the LAST textbox added (the one we last set _txt to refer to). Like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Public Partial Class WebForm1
Inherits System.Web.UI.Page

Protected WithEvents _tx As TextBox

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
_tx = New TextBox
_tx.ID = "textbox1"
Form.Controls.Add(_tx)


_tx = New TextBox
_tx.ID = "textbox2"
Form.Controls.Add(_tx)

End Sub


Private Sub _tx_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles _tx.TextChanged
'do something
End Sub
End Class

If we change the text of the FIRST textbox and put a breakpoint in line 12, we will notice it is NEVER being hit. That is because _tx_TextChanges can handle only one reference: The one variable _tx was assigned last, and that is the reference for the SECOND text box.

The RIGHT way

The right way to handle events in dynamically added controls is to forget the "handles" keyword and use the AddHandler method, like in the following example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
Partial Public Class _Default
Inherits System.Web.UI.Page

Protected _genTextbox As TextBox
Protected _genButton As Button


Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

_genButton = New Button
_genButton.ID = "btn1"
_genButton.Text = "btn1"
AddHandler _genButton.Click, AddressOf Click1
Form.Controls.Add(_genButton)


_genButton = New Button
_genButton.ID = "btn2"
_genButton.Text = "btn2"
AddHandler _genButton.Click, AddressOf click2
Form.Controls.Add(_genButton)

Dim b As New Button
b.ID = "btn3"
AddHandler b.Click, AddressOf Click3
Form.Controls.Add(b)

_genTextbox = New TextBox
_genTextbox.ID = "txt1"
Form.Controls.Add(_genTextbox)

_genTextbox = New TextBox
_genTextbox.ID = "txt2"
Form.Controls.Add(_genTextbox)


End Sub


Private Sub Click1(ByVal sender As Object, ByVal e As System.EventArgs)
DirectCast(Me.FindControl("txt1"), TextBox).Text = "button 1 pressed"
DirectCast(Me.FindControl("txt2"), TextBox).Text = ""
End Sub
Private Sub Click2(ByVal sender As Object, ByVal e As System.EventArgs)
DirectCast(Me.FindControl("txt1"), TextBox).Text = ""
DirectCast(Me.FindControl("txt2"), TextBox).Text = "button 2 pressed"
End Sub
Private Sub Click3(ByVal sender As Object, ByVal e As System.EventArgs)
DirectCast(Me.FindControl("txt1"), TextBox).Text = "button 3 pressed"
DirectCast(Me.FindControl("txt2"), TextBox).Text = "button 3 pressed"
End Sub

End Class

In this code, we create three buttons and two textboxes dynamically. Each button is assigned an event handler which does something to the two textboxes. Let's examine some interesting things here:

For the buttons, we didn't use the "withevents" keyword in line 4. Of course, we didn't use the "handles" keyword as well. We just assigned event handlers to our two buttons in lines 9 and 14 respectively, passing the addresses of the Click1 and Click2 methods which we have constructed by hand. Although there is only ONE variable for the two buttons, the handlers both work fine! That is because the handlers are not hooked to the _genbutton variable and its current reference any more, as when the "handles" keyword is used.

You might also have noticed something strange - a third button being initialized at line 16, with a variable totally local to the Page_Load sub, which is too assigned an event handler -  and works just fine! So you don't even have to declare protected variables as placeholders for references if you don't want to. Local variables will do just the same.

You have already probably noticed that we are setting the ID property of every control we create. Why? Well, since these controls have not been officially declared in the page, intellisense does not work for them. So, the only way to find what we have constructed is to use the FindControl method which takes a control ID as an argument and returns an object which we must cast to the right type, as is done in all 3 event handlers.

 

Conclusion

In order to achieve fully dynamic addition of controls in web forms you have to:

- Forget about the "handles" keyword. Use the AddHandler method instead. Copy signatures from the event handling methods generated when you use the "withevents" and "handles" keywords in Visual Studio, if you feel you can't remember that argument each handler uses, and create your own handling methods which you'll link to your controls with the help of the AddHandler method.

- No need to declare protected stuff if you don't need to. Even local variables will do. If you do declare protected / private stuff, event handlers will work quite as well since they aren't hooked to what your variable refers to at runtime.

- Always set the control's ID property so you can find it again at runtime using the FindControl method.

Hope that helped a bit.

 

kick it on DotNetKicks.com

 

 

 

Δημοσιεύτηκε στις από το μέλος cap | 1 σχόλια
Δημοσίευση στην κατηγορία:

Οι εφαρμογές bug / issue tracking που χρησιμοποιούμε

Σε μια προσπάθεια συγκέντρωσης των bug / issue tracking προγραμμάτων που χρησιμοποιούν οι Ελληνες developers, έχω δημοσιεύσει στο Google Documents ένα public spreadsheet στη διεύθυνση http://spreadsheets.google.com/ccc?key=pzX382cJsXGbe_H9rbLo7Pw&hl=en. Εκεί μπορείτε να δείτε τι έχει προστεθεί μέχρι τώρα και να συμπληρώσετε τα δικά σας.

Το συγκεκριμένο υλικό, αν και εφόσον αποκτήσει το απαραίτητο περιεχόμενο, θα δημοσιευτεί εδώ και στην αντίστοιχη συζήτηση του dotNETZone.gr.

Το συγκεκριμένο document μπορείτε να το δείτε read-only. Αν έχετε ήδη λογ/σμό στο gmail, μπορείτε να μου στείλετε με προσωπικό μήνυμα στο dotnetzone.gr το email σας ωστε να σας προσθέσω στους collaborators για να μπορείτε να κάνετε επεξεργασία και να προσθέσετε και τις δικές σας εγγραφές. Ως collaborators, μπορείτε και εσείς να στείλετε προσκλήσεις collaboration σε τρίτους.

Ας φτιάξουμε μαζί μια πλήρη λίστα, όχι οποιουδήποτε software κυκλοφορεί, αλλά αυτών που ΧΡΗΣΙΜΟΠΟΙΟΥΜΕ. Σας περιμένω.

 

Δημοσιεύτηκε στις από το μέλος cap | 5 σχόλια
Δημοσίευση στην κατηγορία: , ,

Δημιουργία AJAX master-detail interface με custom SQL Queries σε σελίδα του dotNETNuke με τη χρήση του ListX Module

Προειδοποίηση: Το άρθρο αυτό προϋποθέτει ότι γνωρίζετε την ύπαρξη και το βασικό χειρισμό του ListX module από την Bi4ce και οτι γνωρίζετε ορισμένα βασικά πράγματα σε σχέση με το DotNetNuke (όπως π.χ. το πώς να εγκαταστήσετε modules). Για να εφαρμόσετε τα όσα αναφέρονται στο άρθρο θα πρέπει να έχετε εγκατεστημένο το ListX module στο DotNetNuke portal σας.

(Το πρωτότυπο άρθρο δημοσιεύτηκε από εμένα στα Αγγλικά, εδώ: http://dnnuke.blogspot.com/2007/09/using-listx-component-to-create.html. Το παρόν αποτελεί προσαρμογή στα Ελληνικά, με σχεδόν το ίδιο περιεχομένο).

Για όσους δεν το γνωρίζουν, το ListX σας επιτρέπει να "τραβάτε" και να παρουσιάζετε δεδομένα από τη βάση του dotNEtNuke, ή από κάποια τρίτη εξωτερική βάση δεδομένων και να τα παρουσιάζετε εντός του dotNetNuke, και υποστηρίζει εκτενώς AJAX.

Με την πρώτη ματιά, ο τίτλος της δημοσίευσης μπορεί σας φαίνεται περίπλοκος. Αυτό όμως που θέλω να σας δείξω είναι η λειτουργικότητα του ListX με τη βοήθεια της οποίας όχι μόνο μπορείτε να κάνετε queries σε κάποια database και να δείξετε αποτελεσματα σε grid-style ή repeater-style, αλλά ακόμα και να έχετε detail σελίδες. Ουσιαστικά, θα επιχειρήσουμε να φτιάξουμε ένα master-detail interface τραβώντας δεδομένα από κάποιο πίνακα και χρησιμοποιώντας για αυτό το σκοπό το ListX.

Πρώτα από όλα, θα χρειαστούμε κάποιον πίνακα από τον οποίο θα πρέπει να αντλήσουμε δεδομένα. Για λόγους απλότητας, θα χρησιμοποιήσουμε έναν υπάρχοντα πίνακα του DotNetNuke, ο οποίος περιέχει δεδομένα ακόμα και στην default εγκατάσταση: Τον πίνακα Tabs. Ο πίνακας αυτός περιέχει πληροφορίες για τις σελίδες του DNN (όπως τον τίτλο, το id της σελίδας κλπ). Στην default εγκατάσταση, ο πίνακας περιέχει στοιχεία για όλες τις σελίδες του Admin και του Host καθώς και για την default (home) σελίδα μας. Φυσικά, μπορείτε να χρησιμοποιήσετε κάποιο δικό σας πίνακα για τον ίδιο σκοπό, μέσα στην βάση του DNN ή σε εξωτερική βάση δεδομένων.

Ας δούμε τα δύο SQL queries που θα χρησιμοποιήσουμε για να εμφανίσουμε τα master και detail κομμάτια του interface μας:

Query 1: Το query που θα χρησιμοποιήσουμε για να δείξουμε τις εγγραφές του πίνακα Tabs συγκεντρωτικά (master)
SELECT tabid AS pageid, tabname FROM tabs ORDER BY tabname DESC

Query 2: Το query που θα χρησιμοποιήσουμε για το detail μέρος.
SELECT tabname, title, isvisible, iconfile, tabpath FROM tabs WHERE tabid = @pageid

Αν σας μπερδεύει το @pageid, να σας πω οτι θα δείτε παρακάτω, όταν θα χρησιμοποιήσουμε το query στο ListX module, οτι αυτό θα αντιπροσωπεύει μια παράμετρο η οποία θα αντικατασταθεί στο runtime με το tab id της σελίδας των οποίων τα details θέλουμε να δούμε, ουσιαστικά δηλαδή με το primary key της εγγραφής της οποίας θα δείξουμε τα details.

Επίσης να σημειώσουμε οτι στο Query 1 χρησιμοποιούμε το alias "pageid" για τη στήλη "tabid". Αυτό το κάνουμε γιατί το "tabid" αποτελεί ήδη παράμετρο του querystring στο dotnetnuke και, λόγω του τρόπου με τον οποίο τα διάφορα ListX modules επικοινωνούν μεταξύ τους (χρησιμοποιώντας το querystring, αν δεν πιάσατε το υποννοούμενο), δεν θέλουμε να μπερδευτεί η δική μας παράμετρος με το querystring που χρησιμοποιείται από το DNN.

Ας βάλουμε λοιπόν το πρώτο μας ListX module instance (το "master" κομμάτι του master-detail interface). Προσθέστε ένα ListX instance σε όποια σελίδα θέλετε (αν δεν ξέρετε πώς να το κάνετε αυτό, μην συνεχίσετε να διαβάζετε!).

- Κάντε κλικ στο "View Options" του drop-down μενού του νέου σας module για να μεταφερθείτε στη σελίδα ρυθμίσεων.
- Κάντε κλικ στο εικονίδιο "Query" για να εμφανίσετε την αντίστοιχη ενοτητα και προσθέστε το query no.1:


- Κάντε κλικ στο "Save and Continue".
- Κάντε κλικ στο εικονίδιο "Format" (μπορείτε να ΄ξανακάνετε κλικ στο εικονίδιο "Query" για να κρύψετε την προηγούμενη ενότητα, αν θέλετε).

Το επόμενο βήμα μας είναι ο ορισμός του template βάσει του οποίου θα παρουσιάζονται τα δεδομένα μας. Κάντε κλικ στο εικονίδιο με το μολύβι δίπλα στο "List Item Detail" για να επεξεργαστείτε το list item detail template και να ορίσετε ένα πολύ απλό template όπως το παρακάτω:



Προσέξτε οτι το template αυτό, στην αρχική του μορφή, δεν περιέχει κάποιο ουσιώδες link για να επικοινωνήσουμε με το "detail" τμήμα του interface μας (το οποίο δεν έχουμε ούτως η άλλως φτιάξει ακόμα). Θα προσθέσουμε τον σχετικό κώδικα αργότερα. .


- Κάντε κλικ στο "Save and Continue".
- Κάντε κλικ στο εικονίδιο "Format" ξανά για να κρύψετε, αν θέλετε, αυτή την ενότητα.


Τελειώνοντας την προετοιμασία του πρώτου μας module, θα τσεκάρουμε την επιλογή "Show all records" στην ενότητα General της σελίδας View Options για να μπορέσουμε να δούμε όλες τις εγγραφές, όπως παρακάτω:



- Κάντε κλικ στο "Save Configuration" για να επιστρέψετε στη σελίδα σας.


Να πώς θα φαίνονται τα αποτελέσματα του "master" module:




Εχουμε λοιπόν μια λίστα που προέρχεται από ένα query που κάναμε στον πίνακα tabs, η οποία περιέχει links που (ακομα) δεν οδηγούν πουθενά. Ας ξεκινήσουμε την ετοιμασία του δεύτερου (detail) ListX module και θα επανέλθουμε αργότερα στο πρώτο. Προσθέστε άλλο ένα ListX instance στη σελίδα σας, κάτω από το πρώτο.

Για να μην γίνει τεράστιο αυτό το άρθρο, από εδώ και κάτω δεν θα δίνω οδηγίες για το πώς μπορείτε να μεταβείτε στις διάφορες ενότητες της σελίδας View Options του ListX module. Απλα φροντίστε να κάνετε κλικ στο "Save and Continue" κάθε φορά που ολοκληρώνετε μια ομάδα ρυθμίσεων έτσι ωστε να μην χάσετε κατα λάθος τις ρυθμίσεις σας.

Στο δεύτερο ListX instance μας (το "detail"), πρέπει επίσης να ορίσουμε ένα query για να αντλούμε δεδομένα από τον πίνακα tabs. Θα χρησιμοποιήσουμε το Query no.2:




και θα ορίσουμε επίσης ένα απλό template παρουσίασης στην ενότητα Format:


Μην ξεχάσετε να τσεκάρετε την επιλογή "Show all records" στην ενότητα General της σελίδας View Options.

Αυτό που κάναμε στο δεύτερο module μας θα μας παρουσιάσει τα details μιας εγγραφής που θα επιλέξουμε από το πρώτο μας ListX module. Για να δουλέψει όμως αυτό, πρέπει να κανουμε άλλη μια ρύθμιση στο "detail" listX module μας: Να ορίσουμε την παράμετρο @pageid. Αυτή θα προέρχεται από το QueryString (είναι ο τρόπος με τον οποίο δουλεύει το ListX σε αυτή την περίπτωση), έτσι πρέπει να ορίσουμε κάτι όπως το παρακάτω στην ενότητα Variables της σελίδας View Options στο δεύτερο ListX module μας:



Αν θυμάστε τι είπα για τις παραμέτρους του querystring νωρίτερα, ίσως τώρα κατανοείτε καλύτερα γιατί χρησιμοποιούμε το όνομα pageid αντί του tabidf. Αν χρησιμοποιείτε URLs θα δείτε την παράμετρο κάπως έτσι: /tabid/xxx οπου xxx είναι το id της σελίδας σας ενώ αν δεν χρησιμοποιείτε friendly URLs θα δείτε την παράμετρο να εμφανίζεται κάπως έτσι: /default.aspx?tabid=xxx. Οπως και να έχει, εφόσον αυτή η παράμετρος χρησιμοποιείται για ΚΑΘΕ σελίδα στην οποία μεταβαίνουμε εντός του DNN, πρέπει να ΜΗΝ χρησιμοποιήσουμε αυτό το όνομα για την querystring parameter μέσω της οποίας θα επικοινωνούν τα δύο ListX modules μας. (Ελπίζω να μην σας μπέρδεψα χειρότερα).


- Κάντε κλικ στο "Save Configuration" όταν τελειώσετε με όλες τις ρυθμίσεις για να επιστρέψετε στη σελίδα σας. .

Αυτό που κάναμε ήταν οτι ορίσαμε μια μεταβλητή η οποία θα περιέχεται στο querystring με το όνομα "pageid". Η τιμή της μεταβλητής αυτής θα δοθεί στην παράμετρο @pageid (του δεύτερου query μας) ωστε το WHERE του να φέρει μόνο μια εγγραφή (αυτή με το συγκεκριμένο id).

Περιμένετε όμως. Δεν πρέπει να κάνουμε το πρώτο μας (master) module να επικοινωνεί με κάποιο τρόπο με το δεύτερο (detail) module μας και να "περνάει" αυτή τη μεταβλητή;

Φυσικά. Εφόσον έχουμε μια μοναδική τιμή id για κάθε εγγραφή, είναι η ώρα να τη χρησιιμοποιήσουμε. Μετατρέπουμε το template του ΠΡΩΤΟΥ μας (master) module ως εξής:  




Η lxFetch function είναι μια JavaScript function του ListX η οποία, με λίγα λόγια, κάνει refresh ένα module (με AJAX) περνώντας του όσα name/value pairs χρειάζονται, στο querystring.

Η πρώτη παράμετρος είναι το module ID του module που θέλουμε να φορτώσουμε (fetch). Το module id μπορείτε να το βρείτε με διάφορους τρόπους (ο πιό εύκολος είναι να κοιτάξετε την τιμή της παραμέτρου mid στο querystring, όταν βρίσκεστε στα settings του συγκεκριμένου module - στο listX μπορείτε να χρησιμοποιήσετε και τη λειτουργία debug για να το δειτε). Στην περίπτωσή μας, το id του "detail" module είναι το 375.

Η δεύτερη παράμετρος δεν ειναι και τόσο σημαντική για τους σκοπούς αυτού του άρθρου - στο documentation του listX μπορείτε να βρείτε περισσότερα. Δινουμε την default τιμή 0.

Η τρίτη παράμετρος είναι τα name/value pairs που θέλουμε να περάσουμε στο module που κάνουμε refresh. (Το "detail" listX module στην περίπτωσή μας). Το[pageid] θα αντικατασταθεί με την τιμή του πεδίου tabid της συγκεκριμένης κάθε φορά εγγραφής, και έτσι θα έχουμε μια διαφορετική τιμή για κάθε μας εγγραφή. Η τιμή αυτή θα περάσει στο δεύτερο ListX module μας (detail) ως μεταβλητή του querystring (αν και, λόγω του AJAX, η ίδια η σελίδα μας δεν θα ξαναφορτωθεί, οπότε μην περιμένετε να δείτε την μεταβλητή αυτή στο query string που σας δείχνει ο browser σας) και θα χρησιμοποιηθεί στο detail query μας. 

Το αποτέλεσμα είναι ένα master/detail interface στο οποίο τα περιεχόμενα του "detail" module αλλάζουν ανάλογα με τις επιλογές μας στο "master" module ΧΩΡΙΣ να ξαναφορτώνεται η σελίδα. Φυσικά, το layout μας εδώ είναι "παιδικό" και σίγουρα μπορείτε να κάνετε καλύτερη δουλειά από εμένα! :)


Κάπως έτσι θα φαίνεται το τελικό μας αποτέλεσμα:

 

Κάνοντας κλικ σε οποιδήποτε link του πρώτου listX module, τα περιεχόμενα του δεύτερου ListX module αλλάζουν χωρίς να ξαναφορτώνεται η σελίδα.

Υπάρχουν φυσικα και άλλα ζητήματα, όπως π.χ. το τι μπορείτε να δειχνετε την πρώτη φορά που φορτώνεται η σελίδα (και που δεν έχετε επιλέξει κάτι από το πρώτο listX module), όμως είναι εκτός scope για αυτό το άρθρο. Είναι πάντως εύκολο να εμφανίσετε κάποιο μήνυμα ή ακόμα και να έχετε αρχικά κρυμμένο το δεύτερο module.

Happy ListX'ing!

 

 

 

Δημοσιεύτηκε στις από το μέλος cap | 0 σχόλια
Δημοσίευση στην κατηγορία: ,

Τεχνική παρουσίαση DotNetNuke portal: New Generis

Η κατασκευή του New Generis ξεκίνησε πέρυσι και σήμερα το portal "τρέχει" στην έκδοση 4.3.4 του DotNetNuke. Το portal έχει κατασκευαστεί εξ'ολοκλήρου με DotNetNuke και εδώ αποσκοπώ στο να δώσω κάποιες τεχνικές λεπτομέρειες για την κατασκευή του:

To portal κατασκευάστηκε κατόπιν παραγγελίας, με προδημιουργημένο γραφικό interface από τον πελάτη (HTML) το οποίο και προσαρμόστηκε κατόπιν στο layout του DotNetNuke. Δεν δημιουργήθηκε νέο skin, αλλά έγινε απευθείας προσαρμογή.

Για την πλοήγηση στο top level χρησιμοποιήθηκε static html με "καρφωτά" τα tab ids, ενώ για την πλοήγηση στο αριστερό κομμάτι χρησιμοποιήθηκε το module Sixxac menu, το οποίο διατίθεται δωρεάν. Υπήρχαν ειδικές απαιτήσεις για το navigation στα αριστερά, τις οποίες έχω περιγράψει σε προηγούμενο post μου.

Για την ενότητα News & Events χρησιμοποιήθηκε το module Orizonti NukeNews, κατάλληλα προσαρμοσμένο.

Ειδική εργασία έχει γίνει και στην members-only ενότητα του portal, οπου ερευνητές συμμετέχουν σε 17 work packages, με δικαιώματα που ποικίλουν. Για το σκοπό αυτό δημιουργήθηκαν αντίστοιχα security groups και χρησιμοποιήθηκε εκτενώς το (core) repository module στο οποίο προσαρμόστηκαν κατάλληλα τα security options για κάθε work package.

Χρησιμοποιήθηκαν επίσης τα forums και blogs core DNN modules.

Η παράδοση του portal έγινε χωρίς εισαγωγή περιεχομένου, το οποίο αργότερα εισήγαγαν οι υπεύθυνοι περιεχομένου του portal.

Σημείωση: Ισως παρατηρήσετε οτι το layout "χαλάει" (τραβιέται προς τα δεξιά) σε ορισμένες σελίδες. Αυτό δυστυχώς προκαλείται λόγω κάποιων html tables που έγιναν paste από τους υπεύθυνους περιεχομένου του portal και οι οποίοι έχουν εξαιρετικά μεγάλο πλάτος που ξεπερνά το μέγιστο δοθέν πλάτος για το content pane. Δυστυχώς δεν υπάρχει κάποιος τρόπος να προφυλαχθεί κανείς από αυτό, πλην του να μειώσει το πλάτος των html tables.

 

 

 

Δημοσιεύτηκε στις από το μέλος cap | 0 σχόλια
Δημοσίευση στην κατηγορία:

Καθυστερήσεις στα Vista κατά την αντιγραφή / διαγραφή μεγάλων αρχείων

Ενα θέμα που επηρέασε και εμένα, όπως και πολλούς άλλους, μετά την εγκατάσταση των Vista, ήταν ο ανορθόδοξα μεγάλος χρόνος που έκαναν να αντιγράψουν μεγάλους όγκους αρχείων μεταξύ του ίδιου ή διαφορετικών δίσκων, καθώς και ένα περίεργο error (insufficient system resources) που έβγαινε κατά καιρούς. Μαλιστα αντιγράφοντας από / προς τον δικτυακό μου δίσκο (Mybook 1TB) το πρόβλημα ήταν κάτι περισσότερο από εμφανές.

Φαίνεται οτι το θέμα αυτό έχει πάρει διαστάσεις, με τη Microsoft να έχει ανακοινώσει ένα patch το οποίο όμως ΔΕΝ έχει εμφανιστεί ακόμα στο Windows update (σχετικό thread στο Technet εδώ). Εχει εκδοθεί ένα hotfix, το οποίο όμως επιχείρησα να εγκαταστήσω και το σύστημά μου αρνήθηκε να εγκαταστήσει (δεν δίνω link γιατί φαίνεται οτι κυκλοφορούν παραπάνω από ένα hotfixes που απευθύνονται σε διαφορετικά προβλήματα).

Φαίνεται οτι το πρόβλημα αυτό δεν εμφανίζεται σε όλους και δεν προκύπτει πάντοτε από τα ίδια αίτια. Η λύση που βρήκα όμως και δούλεψε για μένα είναι η εξής:

1. Ανοίγουμε ένα command prompt.
2. Δίνουμε την εντολή netsh int tcp set global autotuninglevel=disabled.
3. Κάνουμε επανεκκίνηση.

Με αυτό τον τρόπο λέμε στα Vista να σταματήσουν να κάνουν auto tuning στο δίκτυο, κάτι που φαίνεται οτι ευθύνεται για τα "δεινά" της μετακίνησης / αντιγραφής / διαγραφής αρχείων. (Τώρα μην με ρωτήσετε γιατί το ένα προκαλεί το άλλο, δεν είμαι τεχνικός! :) )

Σε περίπτωση που αντιμετωπίσετε οποιοδήποτε πρόβλημα, μπορείτε να γυρίσετε τη ρύθμιση στην αρχική της κατάσταση με την εντολή netsh int tcp set global autotuninglevel=normal.

Για περισσότερες πληροφορίες, εδώ: http://www.howtogeek.com/howto/windows-vista/fix-problems-with-copying-large-files-in-windows-vista/

 

 

 

Δημοσιεύτηκε στις από το μέλος cap | 5 σχόλια
Δημοσίευση στην κατηγορία:

Δέκα σημάδια που υποδεικνύουν οτι μάλλον χρεώνετε λίγα ως ελεύθερος επαγγελματίας

Το συγκεκριμένο άρθρο το βρήκα εδώ: http://freelanceswitch.com/humour/top-ten-signs-you-may-be-charging-too-little/ και σκέφτηκα να το μεταφράσω στα Ελληνικά μια και κρύβει πολλές αλήθειες. :)

10:
Οι πελάτες σας πιστεύουν οτι η τιμή που τους χρεώνετε ανά ανθρωποημέρα εργασίας είναι η τιμή ανά ανθρωποώρα.

9: 
Για κάθε προσφορά που υποβάλλετε, παίρνετε αμέσως τη δουλειά.

8:
Αν και δουλεύετε 80 ώρες την εβδομάδα, το επίπεδο του εισοδήματός σας σας καθιστά υποψήφιους για επιδοτήσεις από την κοινωνική πρόνοια.

7:
Οι καινούριοι πελάτες σας ρωτάνε πάντοτε που βρίσκεται η παγίδα.

6:
Οι πελάτες πληρώνουν τα τιμολόγιά σας σε μετρητά - από το πορτοφόλι τους.

5:
Δέχεστε emails μίσους από συνάδελφους ελεύθερους επαγγελματίες.

4:
Οι παλιοί σας πελάτες δεν ασχολούνται καν με το να σας ρωτήσουν πόσο θα στοιχίσει κάτι.

3:
Δεν ξεμένετε ποτέ από δουλειά, παρ'όλα αυτά τρέφεστε με κονσέρβες και έτοιμο φαγητό.

2:
Το 12χρονο αδερφάκι σας βγάζει περισσότερα από εσάς ψήνοντας μπιφτέκια σε καντίνα


Και το νούμερο ένα σημάδι οτι χρεώνετε ΠΟΛΥ λίγα:

1:
Δέχεστε τηλεφωνήματα από εταιρίες στην Ινδία που θέλουν να κάνουν outsource τη δουλειά τους σε εσάς.

 

 

 

Δημοσιεύτηκε στις από το μέλος cap | 3 σχόλια
Δημοσίευση στην κατηγορία:

Jet Unspecified Error στον IIS7 όταν επιχειρούμε να συνδεθούμε σε MS Access Database

Δημοσιεύω αυτό εδώ μια και αντιμετώπισα το πρόβλημα πρόσφατα και ίσως βοηθήσει και άλλους συναδέλφους.

Πρόσφατα "μετακόμισα" στα Vista και τον αξιαγάπητο IIS7. Χρειάστηκε όμως να δουλέψω ένα παλιό site γραμμένο σε Classic ASP 3.0 και Access database. Αφού έκανα ο,τι χρειαζόταν, επιχείρησα να συνδεθώ και πήρα το φρικτό παρακάτω:

Microsoft JET Database Engine error '80004005'

Unspecified error

Μην έχοντας κάποιο άλλο προφανές σφαλμα μια και το site έπαιζε αλλού, και εχοντας ακούσει οτι και σε παλιότερες εκδόσεις των Windows ενδέχεται να χρειάζεται να δοθούν δικαιώματα r/w στον IUSR_machinename χρήστη στον φάκελο %temp% (που υποτίθεται οτι είναι φάκελος συστήματος), πήγα και έκανα αυτό ακριβώς. Αμ δε! Στα vista ο φάκελος %temp% κάνει map στον logged in χρήστη, δίνει δηλαδή κάτι σαν: C:\Users\sotirisf\AppData\Local\Temp

Φυσικά με αυτό δεν λύνεται το πρόβλημα. Ομως μετά από ΠΟΛΥ ψάξιμο βρήκα το εξής το οποίο μου έλυσε το πρόβλημα: Ο φάκελος στον οποίο πρέπει να προστεθεί ο IUSR χρήστης (προσοχή: στα vista λέγεται ΑΚΡΙΒΩΣ IUSR χωρίς το underscore και το όνομα του μηχανήματος μετά) είναι ο c:\windows\serviceprofiles\networkservice\appdata\local\temp !

To original post εδώ: http://www.issociate.de/board/post/408540/IIS7_and_Access_Database:_vague_error,_nothing_in_logs!.html

My pills, my nerves and a taxi.

 

 

 

Δημοσιεύτηκε στις από το μέλος cap | 1 σχόλια
Δημοσίευση στην κατηγορία:

Κυκλοφόρησε ο Maxthon 2.0

Ο Maxthon, αν δεν τον ξέρετε ήδη, είναι ένα shell που χρησιμοποιεί τη μηχανή του IE αλλά τα κάνει όλα πολύ πιό γρήγορα και πιό καλά! (Τώρα το πώς γίνεται αυτό μόνο οι ίδιοι το ξέρουν). Ηδη από την έκδοση 1.0 και πολύ πριν τον IE χρησιμοποιούσε tabbed browsing, ενώ υποστηρίζει mouse gestures, drag&drop των links σε νέα tabs και διάφορα άλλα καλούδια που στον ΙΕ7.0 είναι εφικτά μόνο μέσω plugins όπως το IE7Pro.

Και μια και μιλάμε για plugins, ο Maxthon έχει ένα εξαιρετικά μεγάλο οπλοστάσιο από plugins (μην ξεχάσετε να δείτε το εκπληκτικό del.icio.us sidebar που δεν το βρίσκετε - πιστεύω - πουθενά αλλού) καθώς και μια πληθώρα skins τα οποία αλλάζουν κυριολεκτικά με το πάτημα ενός κουμπιού.

Ταχύτατος, αξιόπιστος, και γεμάτος καλούδια όπως αυτόματη συμπλήρωση φορμών, ad blockers, file filters, undo features, screen capture tools και άλλα πολλά. Μοναδικό μειονέκτημα: Toolbars ειδικά για τον IE δεν "παίζουν" στο Maxthon (εμένα φυσικά διόλου δεν με πειράζει).

Τον χρησιμοποιώ προσωπικά εδώ και αρκετά χρόνια, και, επειδή είναι IE χωρίς όμως τη βραδύτητα του κανονικού IE, δεν τον αλλάζω με τίποτα. Χρόνος φόρτωσης μηδενικός, η ταχύτητά του στο χειρισμό μπορεί άνετα να συγκριθεί με αυτή του Opera, ενώ διαθέτει αρκετά από τα καλούδια που θα βρείτε και στο Firefox. Η έκδοση 2.0 είναι συμβατή με Vista ενώ τα downloads του Maxthon συνολικά ξεπερνούν τα 100.000.000.

 

 

 

Δημοσιεύτηκε στις από το μέλος cap | 2 σχόλια
Δημοσίευση στην κατηγορία:

Κυκλοφόρησε το DotNetNuke 4.5.3 Greek Language Pack

Χάρη στον κ. Αγγελο Ξυπολιά της Xelixis.NET έχουμε πλέον στα χέρια μας το φρεσκότατο Greek DNN Language Pack για την έκδοση 4.5.3 το οποίο μπορείτε να βρείτε εδώ. Συγχαρητήρια Αγγελε και συνέχισε να μας δίνεις όμορφα Ελληνικα localizations!

 

 

 

Δημοσιεύτηκε στις από το μέλος cap | 1 σχόλια
Δημοσίευση στην κατηγορία:

DotNetNuke Login Page: Κλειδωθήκατε έξω; Ο κλειδαράς!

Εχει συμβεί σε πάρα πολλούς, συνέβη και σε μένα. Σε ένα πρόσφατο project, η συνεργάτις μου άλλαξε κατά λάθος την default login page του dotNetnuke (μέσα από τα site settings) και έβαλε μια σελίδα η οποία δεν περιείχε user login module.

Αυτό είχε ως αποτέλεσμα, φυσικά, να μην έχουμε από πουθενά πρόσβαση σε login page και φυσικά να μην μπορούμε να κάνουμε login στο portal.

Ψάχνοντας, ανακάλυψα οτι ένα σωρό κόσμος έχει "κλειδωθεί" έξω από το dotNetNuke του για τον ίδιο λόγο. Φυσικά, η λύση είναι απλή:

1. Αν έχετε πρόσβαση στη database, μπορείτε να βρείτε τον πίνακα Portals και να αλλάξετε το πεδίο LoginTabId σε NULL ωστε το dotNetNuke να "σερβίρει" την default Login Page. (Το tab id που θα δείτε εκεί είναι το id της σελίδας που βάλατε κατά λάθος). Εναλλακτικά, μπορείτε να τρέξετε το εξής query: Update Portals Set LoginTabId=null Where PortalId=xx
(οπου xx το id του portal - αν έχετε μόνο ένα portal, το id του θα είναι 0).

2. Αν δεν έχετε πρόσβαση στη database, τότε ο John Mitchell έχει τη λύση: Σε αυτό εδώ το post του σας δίνει μια σελίδα την οποία μπορείτε να ανεβάσετε στο portal σας, να την καλέσετε και να κάνει αυτή τη "βρώμικη" δουλειά της ενημέρωσης της database για σάς.

Οποια από τις δύο λύσεις και αν ακολουθήσετε, το αποτέλεσμα φυσικά θα είναι να ξαναδείτε τα περιζήτητα login/password κουτάκια! :)

 

 

 

Δημοσιεύτηκε στις από το μέλος cap | 3 σχόλια
Δημοσίευση στην κατηγορία:

ResEx: Μεταφράστε resource files side-by-side (και όχι μόνο)

Ο συν-moderator στο dotNetZone.gr, Δημήτρης Παπαδημητρίου (εδώ θα βρείτε περισσότερα για αυτόν) ολοκλήρωσε την πρώτη έκδοση του ResEx, ενός resource file editor που σας βοηθά να βλέπετε εύκολα (σε δενδρική μορφή) και να μεταφράζετε το περιεχόμενο resource files, side-by-side με την ξενόγλωσση έκδοση του αρχείου. Ο ResEx είναι εξαιρετικά απλός στη χρήση και προσφέρει εκπληκτική ευκολία στην μετάφραση. Αν - λέμε τώρα - έχετε προσπαθήσει να μεταφράσετε π.χ. τα resource files ορισμένων modules του dotNetNuke, θα καταλάβετε σίγουρα τι εννοώ!

Ορίστε όρισμένα γνωρίσματα του ResEx όπως τα αναφέρει ο Δημήτρης στο site του: Translate values side by side (just like the old time classic VB6 resource editor), Lock specific strings so that translator does not translate them, Restrict length of translating strings, Ensure correct translation of strings with placeholders {0} {1} ..., Warnings about shortcut characters (string containing &) , View resource strings in tree form, Translate resources without Visual Studio IDE, Search inside resource files while translating.

Θέλετε κι άλλα; Είναι τσάμπα, είναι .NET και είναι Ελληνικό!

http://www.papadi.gr/resex.aspx

 

 

 

Δημοσιεύτηκε στις από το μέλος cap | 1 σχόλια
Δημοσίευση στην κατηγορία:

Υπαρξιακά προβλήματα WinForms controls: Το NumericUpdown control

Φτιάχτηκε για να μας διευκολύνει τη ζωή, αλλά γιά κοιτάξτε τι ωραία που μας την κάνει μαντάρα άμα το ζορίσουμε... Απλά πραγματάκια: Εχω ένα NumericUpDown control σε μια φορμίτσα και θέλω ο άμοιρος να του δίνω τιμές και αυτό να τις παίρνει. Ολα καλά.

Ομως, για να πατήσουμε ένα Backspace εντός του NumericUpDown και να δούμε τι θα κάνει μόλις αλλάξουμε focus...ΣΩΣΤΑ μαντέψατε, δεν παίρνει default τιμή 0, αλλά κρατάει την παλιά του τιμή! Μόνο που το άτιμο δεν μας το δείχνει, και έτσι, ενώ είναι κενό οπτικά, στην πραγματικότητα έχει τιμή!

(Για να μην πω τι @%$#@#% έριξα που το είχα και databound σε object και αναρωτιόμουνα "γιατί βάζει έκπτωση ενώ του την έσβησα"; )

Σαν να μην μας έφταναν αυτά τα ψυχοπλακωτικά, έρχεται και ο τρόπος επίλυσης να μας κάνει τα νεύρα ακόμα πιό τσατσάλια. Για να δούμε τι έκανα λοιπόν στο LostFocus event (άλλοι λένε οτι καλύτερα βέβαια να το βάλουμε στο Validating):

Private Sub nmrDiscount_LostFocus(ByVal sender As Object, ByVal e As System.EventArgs) Handles nmrDiscount.LostFocus
   If nmrDiscount.Text.Equals(String.Empty) Then
      nmrDiscount.Value = 0
      nmrDiscount.Text = "0"
   End If
End Sub

Ωραία. Τι πιό απλό θα μου πείτε;

Για να σας πω κι εγώ με τη σειρά μου: ΠΟΙΟ ΤΕΧΤ PROPERTY ΡΕ ΠΑΛΗΚΑΡΙΑ; Αφού ούτε το Intellisense το βγάζει! Οκ, όλα τα Winforms controls ΥΠΟΤΙΘΕΤΑΙ οτι έχουν ένα text property, αλλά ΕΛΕΟΣ, οχι απλά πρέπει να το ελέγξω (γιατί αυτό είναι τελικά που γίνεται string.empty και όχι το value, αλλά να το ΑΛΛΑΞΩ κιόλας, γιατί αλλιώς το value μεν θα γίνει 0, εγώ θα συνεχίσω να βλέπω το απέραντο κενό στο NumericUpDown μου...)

Το πρόβλημα λύθηκε. Και τα νεύρα μου κορδέλες. Τα χάπια μου!

 

 

 

Δημοσιεύτηκε στις από το μέλος cap | 2 σχόλια
Δημοσίευση στην κατηγορία:

DotNetNuke και δοκιμές με το ISearchable interface

Οταν φτιάχνετε ένα custom module στο DotNetNuke, πολλές φορές μπορεί να χρειάζεται να υλοποιήσετε το ISearchable Interface, το οποίο σας επιτρέπει να ενσωματώσετε στο search του DotNetNuke αποτελέσματα που παράγονται από το δικό σας module. Για παράδειγμα, σε περίπτωση που το module σας αντλεί δεδομένα από δικούς του πίνακες (ας πούμε π.χ. δεδομένα πωλήσεων), υλοποιώντας στο module σας το ISearchable interface λέτε στον scheduler του DotNetNuke να συμπεριλάβει στη διαδικασία indexing και τα δικά σας δεδομένα.

Το ISearchable είναι πολύ ισχυρό, αλλά δυστυχώς δεν υπάρχει εύκολος τρόπος να το δοκιμάσει κανείς παρά να αρχίσει να κάνει searches με λέξεις - κλειδιά, ελπίζοντας οτι μέσα σε αυτές θα βρίσκονται αποτελέσματα που θα προέρχονται από τα δεδομένα του custom module σας. (Η, εναλλακτικά, να "βουτήξετε" στη database και να δείτε τι έγινε index).

O κ. Nik Kalyani εντόπισε το πρόβλημα και δημοσίευσε μια λύση εδώ:
http://www.dotnetnuke.com/Community/BlogsDotNetNuke/tabid/825/EntryID/1100/Default.aspx

Η λύση ουσιαστικά είναι μια .aspx σελίδα την οποία βάζετε στο root του site σας. Δίνοντας το tabid και το moduleid σας επιστρέφει όλα τα αποτελέσματα που έχουν γίνει index για αυτό το συνδυασμό.

Time-saver!

 

 

 

Δημοσιεύτηκε στις από το μέλος cap | 0 σχόλια
Δημοσίευση στην κατηγορία: ,

Databinding και InotifyPropertyChanged - Μαμα, ο BindingManager κάνει του κεφαλιού του!

Στο dotNETZone.gr είχαμε μια ενδιαφέρουσα συζήτηση γύρω από ένα θέμα που προκύπτει με το databinding όταν χρησιμοποιούμε το INotifyPropertyChanged και σηκώνουμε το PropertyChanged event. Σκέφτηκα λοιπόν να παραθέσω το θέμα εδώ για όποιον συνάδελφο ενδιαφέρεται.

 

Το σενάριο (+ backgrounder):

Εχουμε ένα custom business object το οποίο έχει κάποια properties. Θέλουμε να "δέσουμε" αυτά τα properties με simple binding σε αντίστοιχα controls (π.χ. labels) μιας φόρμας, έτσι ώστε όταν αλλάζει κάποιο property να ενημερώνονται οι τιμές των controls της φόρμας χωρίς άλλες διαδικασίες. Εύκολα, γρήγορα, και απλά.

Για να το κάνουμε αυτό, εκτός από το γνωστό μακρινάρι:
MyLabel.Databindings.Add ("Text", myObjectInstance, "ΜyObjectProperty")
για κάθε property MyObject Property του MyInstance που θέλουμε να "δέσουμε" σε κάποιο Text property ενός label οπως το MyLabel, θα πρέπει να υλοποιήσουμε στο Business Object (έστω myObject) το interface INotifyPropertyChanged.

Ετσι, κάθε αλλαγή property θα σηκώνει ένα PropertyChanged event το οποίο θα "μιλάει" με τον υποβόσκων BindingManager και θα ενημερώνει αυτόματα την τιμή των labels στη φόρμα μας.

Σύμφωνα με το MSDN, πρέπει να κάνουμε Implements INotifyPropertyChanged στην κλάση μας και να προσθέσουμε κώδικα όπως ο παρακάτω:

Public Event PropertyChanged As PropertyChangedEventHandler _
Implements INotifyPropertyChanged.PropertyChanged


Private Sub NotifyPropertyChanged(ByVal info As String
   RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(info))
End Sub

Ετσι θα μπορούμε να καλούμε την Sub NotifyPropertyChanged όταν η τιμή κάποιου property αλλάζει, όπως παρακάτω:

Public Property CompanyName() As String
Get
   Return Me.companyNameValue
End Get

Set(ByVal value As String)
   If Not (value = companyNameValue) Then
      Me.companyNameValue = value
      NotifyPropertyChanged("CompanyName")
   End If
End Set
End Property

Οπως ισως προσέξατε, το propertyChanged event θέλει ως παράμετρο το όνομα του property που άλλαξε.

Από εδώ και πέρα, άν έχουμε "δέσει" την τιμή του property CompanyName στο label π.χ. lblCompanyName (κάπως έτσι: lblCompanyName.Databindings.Add ("Text", MyInstance, "CompanyName") οπου MyInstance το instance του class μας που περιέχει το property CompanyName, η τιμή του label θα ενημερώνεται αυτόματα όταν θα γίνονται αλλαγές στο property CompanyName.

Φυσικά, για όσα properties καλούμε την NotifyPropertyChanged θα γίνεται το ίδιο.

 

Το πρόβλημα

Εστω οτι υλοποιούμε αυτή τη λογική για ένα object που έχει π.χ. 10 properties, με ισάριθμα labels σε μια Windows Form. Πολύ γρήγορα θα διαπιστώσουμε οτι συμβαίνει το εξής:

Οταν σηκώνεται ένα PropertyChanged event ενημερώνονται ΟΛΑ τα databound labels της φόρμας με τις τιμές των properties του υποκείμενου business object instance, ανεξαρτήτως αν δεν αφορούν το property που άλλαξε ή άν έχουν αλλάξει ή οχι τιμή.

Αυτό σημαίνει οτι για κάθε PropertyChanged event που σηκώνεται θα έχουμε στο συγκεκριμένο σενάριο 10 ενημερώσεις! Και αυτό έχοντας αλλάξει μόνο την τιμή ενός property!

Αυτό μπορείτε να το επαληθεύσετε πολύ εύκολα αποφεύγοντας να "σηκώσετε" το PropertyChanged event σε κάποιο property του object σας. Αλλάζοντας την τιμή του property, φυσικά δεν ενημερώνεται το bound πεδίο μια και το PropertyChanged event δεν έχει σηκωθεί. Ομως, αν ενημερώσετε ΚΑΠΟΙΟ ΑΛΛΟ property που ΣΗΚΩΝΕΙ το PropertyChanged event, θα δείτε με έκπληξη οτι θα ενημερωθεί και η τιμή του control που είναι bound στο πρώτο property!

Σύμφωνα με τη γνώμη ορισμένων όπως εδώ, συμβαίνει το εξής:

"Any property changed event will result in
BindingManagerBase.PushData which causes a PushData on *all* its Bindings."

Ομως, αυτό μας οδηγεί στο εξής συμπέρασμα:

Αν έχω 10 properties bound σε αντίστοιχα controls και ενημερώσω και τα 10, τότε ο συνολικός αριθμός ενημερώσεων που θα γίνει στα controls θα είναι 10 x 10 = 100! Γιατί για κάθε property που σηκώνει ένα PropertyChanged event γίνεται ενημέρωση σε ΟΛΑ τα bound controls που έχω!

Και φυσικά στην εξής απορία:

Τότε ΤΙ το θέλουμε το όνομα του property στο event;

Για τη δεύτερη απορία είχαν την απάντηση στο DevelopersDex:

> What's the point of specifying a property name in the

When it comes to WinForms databinding there is no point afaik.    But
remember that INotifyPropertyChanged can be used elsewhere too, eg. for the
PropertyGrid (dunno if it refreshes all properties on change there) and also
for WPF (where it doesn't refresh all properties on change).

Το θέμα είναι όμως οτι έχουμε ένα πρόβλημα. Τις 100 ενημερώσεις! Πώς θα μπορούσαμε να αποφύγουμε αυτό το πρόβλημα; Για να το κάνω ακόμα πιό σοβαρό, φανταστείτε οτι έχουμε ένα ΜΕΓΑΛΟ object με 100 properties bound σε αντίστοιχα controls μιας φόρμας. Αν αλλάξουμε ΟΛΑ τα properties (π.χ. κάνοντας ένα fetch από τη βάση δεδομένων) τότε θα έχουμε 100 x 100 = 10000 ενημερώσεις!

 

Η λύση (στο σημείο που μας ενδιαφέρει)

Αφού δεν μπορούμε να το αποφύγουμε, μαλλον πρέπει να καθήσουμε και να το απολαύσουμε. Ο κ. Κελαιδίτης (kelman) όμως στο dotNETZone.gr έχει διαφορετική άποψη. Μπορούμε, τουλάχιστον, να αποφύγουμε τις πολλαπλές ενημερώσεις ως εξής, σύμφωνα με τον κώδικα που παραθέτει:

Είναι αναπόφευκτο ωστόσο, όταν δεν ξέρεις ποιό από τα 1000 properties θα αλλάξει. Αν ξέρεις, βάζεις το PropeprtyChanged μόνο στο property που σε ενδιαφέρει. Από την άλλη, μπορείς να αποφύγεις έναν τέτοιο σενάριο υλοποιώντας τον κατάλληλο μηχανισμό. Πρόσεξε: Ο designer όταν σχεδιάζει τη φόρμα βάζει στην αρχή Me.SuspendLayout και αφού τοποθετήσει όλα τα controls, στο τέλος Me.ResumeLayout(False) ώστε να αποφύγει τον τμηματικό σχεδιασμό της φόρμας. Το ίδιο κάνει και το DataRow object όπου με DataRow.BeginEdit κάνεις suspend την ενεργοποίηση των events που προκύπτουν από τα validation rules και στο τέλος με DataRow.ΕndEdit κάνεις ένα συνολικό validate. Αντίστοιχα κι εσύ μπορείς να φτιάξεις ένα ζευγάρι Begin/End ή Suspend/Resume για τη business κλάση σου. Πχ:

Imports System.ComponentModel

Public Class Customer
Implements INotifyPropertyChanged

Public Event PropertyChanged(ByVal sender As Object, ByVal e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged

Private _CustomerID As String
Private _CustomerName As String

Private notificationSuspended As Boolean = False

Public Property CustomerID() As String
Get
   Return _CustomerID
End Get
Set(ByVal value As String)
   _CustomerID = value
   RaisePropertyChanged("CustomerID")
End Set
End Property

Public Property CustomerName() As String
Get
   Return _CustomerName
End Get
Set(ByVal value As String)
   _CustomerName = value
   RaisePropertyChanged("CustomerName")
End Set
End Property

Public Sub SuspendNotification()
   notificationSuspended = True
End Sub

Public Sub ResumeNotification(ByVal notifyChanges As Boolean)
   notificationSuspended = False
   If notifyChanges Then
      RaisePropertyChanged(String.Empty)
   End If
End Sub

Private Sub RaisePropertyChanged(ByVal propertyName As String)
   If Not notificationSuspended Then
      RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
   End If
End Sub
End Class


Έτσι, αν πεις

x.CustomerID = "a"
x.CustomerName = "b"

τρέχουν δύο events. Αν πεις

x.SuspendNotification()

x.CustomerID &= "2"
x.CustomerName &= "2"

x.ResumeNotification(True)

τρέχει ένα event. Και αν πεις

x.SuspendNotification()

x.CustomerID &= "3"
x.CustomerName &= "3"

x.ResumeNotification(False)

 

 

 

Δημοσιεύτηκε στις από το μέλος cap | 0 σχόλια
Δημοσίευση στην κατηγορία:

IE7Pro plugin: Η απάντηση του IE7 στον Maxthon

Εδώ και καιρό, παρ'ότι έχω εγκαταστήσει τον ΙΕ7 στο σύστημά μου, χρησιμοποιούσα τον Maxthon λόγω των περισσότερων ευκολιών που μου προσέφερε. Ουσιαστικά, βέβαια, χρησιμοποιούσα τον IE7 ούτως η άλλως, μια και ο Maxthon είναι απλά ένα shell για τον IE, χρησιμοποιεί δηλαδή τη μηχανή του IE. Ομως, ο Maxthon μου προσέφερε (από τότε που ο IE ήταν στην έκδοση 6) τα εξής: Tabbed browsing, mouse gestures, super drag & drop (σέρνεις ένα link σε μια κενή περιοχή της σελίδας και αυτό ανοίγει σε νέο tab).

Σήμερα ανακάλυψα ένα πανέμορφο plugin για τον IE7 που του προσφέρει όλα αυτά που με έκαναν να προτιμώ (παλιότερα) τον Maxthon. Το όνομα αυτού IE7Pro. Τι κάνει αυτό;

- Mouse gestures: Για παράδειγμα, σέρνοντας το ποντίκι με πατημένο το πλήκτρο κάτω και δεξιά κλείνει το current tab. Σέρνοντας το ποντίκι προς τα αριστερά κάνετε back στη σελίδα, και πολλά άλλα.

- Super drag & drop: Σερνετε ένα link σε ένα κενό χώρο στη σελίδα και αυτό ανοίγει σε νέο tab.

Φανταστείτε τώρα εμένα, ο οποίος πολλές φορές θέλω να ανοίξω τα 20 πρώτα results μιας μηχανής αναζήτησης, να ρίξω μια γρήγορη ματιά και να τα κλείσω. Με το συνδυασμό super drag & drop και mouse gestures, η διαδικασία παίρνει μερικά δευτερόλεπτα!

Η αλήθεια είναι οτι άργησε να φτιαχτεί ένα τέτοιο plugin, για τον Firefox υπάρχει ήδη εδώ και αρκετό καιρό, και ο Οpera υποστηρίζει αυτή τη λειτουργικότητα. Ομως, εχω τώρα ένα λόγο παραπάνω για να χρησιμοποιήσω τον ΙΕ7 πλέον.

Επιπρόσθετα να σας πω οτι το IE7Pro σας παρέχει ad filter (whitelist/blacklist με wildcards), και αλλαγή του user agent.

 

 

 

 

Δημοσιεύτηκε στις από το μέλος cap | 4 σχόλια
Δημοσίευση στην κατηγορία:

ConnectionStrings.com: Φτιάξτε εύκολα το connection string σας

Ειναι παλιό, αλλά μπορεί να μην το έχετε πάρει χαμπάρι ακόμα: Οι τύποι στο www.connectionstrings.com έχουν συγκεντρώσει μια τεράστια συλλογή από πρότυπα connection strings για κάθε είδους database (και όχι μόνο). Την επόμενη φορά λοιπόν που θα έχετε απορία για το πώς πρέπει να συντάξετε το δικό σας connection string, ανατρέξτε εκεί και δεν υπάρχει περίπτωση να μην σας λυθεί.

 

 

 

 


Δημοσιεύτηκε στις από το μέλος cap | 1 σχόλια

Φύλλα γρήγορης αναφοράς (cheat sheets)

Ο κύριος που θα βρείτε σε αυτή τη διεύθυνση: http://www.ilovejackdaniels.com/cheat-sheets/ έχει μαζέψει ένα πακέτο από cheat sheets που είναι σχεδιασμένα για να τα τυπώσετε σε μια Α4 σελιδούλα και να τα έχετε δίπλα σας για γρήγορη αναφορά. Μεταξύ αλλων περιλαμβάνονται τα εξής: HTML, CSS, ASP 3.0, Regular Expressions κλπ. Τα cheat sheets διατίθενται σε μορφή PDF και PNG.

Επίσης μπορείτε να παρακολουθείτε αυτόν εδώ τον κύριο: http://john-sheehan.com/blog/index.php/net-cheat-sheets/ ο οποίος όχι μόνο παρακολουθεί τον απο πάνω κύριο αλλά μαζεύει και υλικό για cheat sheets από άλλες πηγές. Τελευταία του προσφορά ένα .NET String Format Quick Reference (σε μορφή PDF)

 

 

 

Δημοσιεύτηκε στις από το μέλος cap | 2 σχόλια
Δημοσίευση στην κατηγορία:

DotNetKicks.com: Social bookmarking for the .NET Framework

Δεν χρειάζεται να πω παραπάνω. Είναι μια μηχανή social bookmarking η οποία εξειδικεύεται στο περιεχόμενο για .NET. Μπορείτε να τη δείτε στη διεύθυνση http://www.dotnetkicks.com, και αν εγγραφείτε έχετε και την προσωπική σας σελίδα. Ορίστε η δική μου: http://www.dotnetkicks.com/users/sotirisf

Δυστυχώς οι δημιουργοί ήταν διστακτικοί στο να απαντήσουν θετικά στην ερώτηση που τους έκανα για δημοσίευση περιεχομένου σε γλώσσα άλλη πλην της Αγγλικής, με το επιχείρημα οτι η πλειοψηφία του κόσμου διαβάζει Αγγλικά. Παντως ακομα και έτσι παραμένει μια αξιόλογη υπηρεσία. Ειναι στα πρώτα της βήματα και καλό είναι να την γνωρίσει ο κόσμος γιατί φαίνεται οτι οι άνθρωποι έχουν όρεξη.

Δινουν και κουμπάκι να βάζετε στις δημοσιεύσεις, καθώς και script για τα feeds τους.

 

Δημοσιεύτηκε στις από το μέλος cap | 1 σχόλια
Δημοσίευση στην κατηγορία:

Introducing System.Transactions in .NET 2.0

Επεσα σήμερα επάνω σε αυτό το πολύ εκτενές document που έχει δημοσιεύσει η Microsoft και διαθέτει προς download, το οποίο περιγράφει αναλυτικά τη χρήση του νέου System.Transactions namespace.

Ελπίζω να σας φανεί χρήσιμο.

http://www.microsoft.com/downloads/details.aspx?familyid=AAC3D722-444C-4E27-8B2E-C6157ED16B15&displaylang=en

 

Δημοσιεύτηκε στις από το μέλος cap | 0 σχόλια
Δημοσίευση στην κατηγορία:
Περισσότερες Δημοσιεύσεις Επόμενη »