Menu w wygodny sposób można zaprojektować z użyciem XAMLa.
sobota, 6 marca 2010
Praca z Menu w WPF
Menu w wygodny sposób można zaprojektować z użyciem XAMLa.
Praca z Bitmapami w WPF
1. Wczytywanie obrazka do kontrolki Image:
Zadanie to można wykonać na kilka sposobów: strumień, pobranie z żądanej lokalizacji sieciowej lub ścieżka. Najprostszą i najczęściej stosowaną opcją jest wczytanie ze ścieżki:
Zobaczmy na przykład:
Kod może trochę bardziej rozbudowany od znanego z WinForms ale za to działający znacznie szybciej. O ile szybciej? O tym przekonamy się podczas tego testu:
Jak widać czas wynosi około 42 ms co jest dużo lepszym rezultatem. Kolejne czasy na poziomie 9 - 13 ms są wynikiem używania przez WPF Intelligent Redrawing (więcej o tym narzędziu można poczytać na stronach msdn).
Jeżeli mowa o zamianie na skalę szarości nie można pominąć tego co sam framework oferuje. Dzięki klasie FormatConvertedBitmap mamy możliwość konwersji obrazka na dowolną skalę. Przykład:
Memento Pattern
W swoim aktualnym projekcie, potrzebowałem stworzyć mechanizm umożliwiający cofnięcie zmian wprowadzonych w obrazie. Dzięki wzorcowi Memento można w bardzo łatwy i szybki sposób uzyskać taką funkcjonalność.
Co nam daje Memento?
Pozwala na zachowanie całego stanu obiektu (lub tyle ile potrzebujemy), w celu późniejszego jego odtworzenia, bez naruszenia zasad enkapsulacji.
Spójrzmy na poniższy diagram klas:
Mamy tutaj 3 klasy:
Orginator - jest to obiekt którego stan wewnętrzny chcemy zachować. Poprzez metodę CreateMemennto() tworzy "kopię zapasową" samego siebie a dzięki metodzie SetMemento(Memento) może się odtworzyć z kopi.
Memento - obiekt który jest kopią oryginalnego obiektu. Dzięki metodą GetState() i SetState() pozwalają na odczyt i zapis stanu obiektu.
Caretaker - obiekt ten zarządza obiektami Memento
Przykłady zawsze lepiej działają na wyobraźnię, dlatego spójrzmy na oto taki przykład. Mamy aplikację w której użytkownik wypełnia jakieś pola. Niech to będzie Imię, Nazwisko i wiek. Przyjmijmy, że wygląda ona tak:
Przyjmijmy, że po naciśnięciu przycisku dane zapisują się do bazy danych. Teraz nasz użytkownik wpisuje swoje dane, wciska ok i nagle przypomina mu się że źle wpisał nazwisko. Są dwa wyjścia: wpisze wszystko od początku albo kliknie przycisk cofnij i wpisze poprawne dane. W tym konkretnym przypadku nie wiele będzie kosztowała go pomyłka, jeżeli jednak pól by było więcej to możliwość cofnięcia wprowadzonych danych będzie z pewnością bardzo przydatna. Kod aplikacji:
public class Person
{
private string _firstName;
private string _lastName;
private int _age;
public string FirstName
{
get
{
return _firstName;
}
set
{
_firstName = value;
}
}
public string LastName
{
get
{
return _lastName;
}
set
{
_lastName = value;
}
}
public int Age
{
get
{
return _age;
}
set
{
_age = value;
}
}
/// <summary>
/// Przywraca poprzedni stan obiektu
/// </summary>
/// <param name="memento"></param>
public void SetMemento(Memento memento)
{
this._age = memento.Age;
this._firstName = memento.FirstName;
this._lastName = memento.LastName;
}
/// <summary>
/// Zapisuje aktualny stan obiektu
/// </summary>
/// <returns></returns>
public Memento CreateMemento()
{
return new Memento(_firstName, _lastName, _age);
}
}
public class Memento
{
private string _firstName;
private string _lastName;
private int _age;
public string FirstName
{
get
{
return _firstName;
}
set
{
_firstName = value;
}
}
public string LastName
{
get
{
return _lastName;
}
set
{
_lastName = value;
}
}
public int Age
{
get
{
return _age;
}
set
{
_age = value;
}
}
public Memento(string firstName, string lastName, int age)
{
_firstName = firstName;
_lastName = lastName;
_age = age;
}
}
public class Caretaker
{
private Memento _memento;
public Memento Memento
{
get
{
return _memento;
}
set
{
_memento = value;
}
}
}
środa, 3 marca 2010
Tworzenie web serwisu WCF cz. 3
ASP.NET
Zaczniemy od aplikacji webowej.
1. Otwieramy stworzony przez nas ostatnio projekt, klikamy prawym przyciskiem myszy i wybieramy Add New Project...
2. Wybieramy ASP.NET Web Application, nadajemy nazwę i klikamy Ok. Po zatwierdzeniu powinniśmy otrzymać taki widok naszych projektów:
Aplikację podzieliłem na 3 oddzielne podstrony:
Pierwsza będzie odpowiedzialna za dodanie nowego klienta do bazy danych. Druga pozwoli na wyświetlenie klienta o określonym Id. Ostatnia wyświetli wszystkich klientów w bazie. A więc do dzieła :)
3. Usuwamy z naszego projektu plik Default.aspx i dodajemy nowy plik: MasterPage.Master. Pozwoli nam to na stworzenie menu, które będzie na każdej podstronie naszego serwisu, bez konieczności kopiowania na wszystkie podstrony kodu odpowiedzialnego za menu.
4. Do utworzonego MasterPaga dodajemy prostą tabelkę z jednym wierszem i dwiema komórkami:
<%@ Master Language="C#" AutoEventWireup="true"
CodeBehind="MasterPage.master.cs" Inherits="
WebPage.MasterPage" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0
Transitional//EN" "http://www.w3.org/TR/xhtml1/
DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title></title>
<asp:ContentPlaceHolder ID="head" runat="server">
</asp:ContentPlaceHolder>
</head>
<body>
<form id="form1" runat="server">
<table border="2" cellpadding="10">
<tr align="left" valign="top">
<!--Menu naszej strony --><td>
<asp:HyperLink ID="HyperLink1" runat=
"server">Add new customer</asp:HyperLink>
<br />
<asp:HyperLink ID="HyperLink2" runat=
"server">Customer information</asp:HyperLink>
<br />
<asp:HyperLink ID="HyperLink3" runat=
"server">Show all customer</asp:HyperLink>
</td>
<!-- Zawartość strony --><td>
<asp:ContentPlaceHolder runat="server"
ID="contetnPlaceHolder"></asp:ContentPlaceHolder>
</td>
</tr>
</table>
</form>
</body>
</html>
<%@ Page Title="" Language="C#" MasterPageFile=
"~/MasterPage.Master" AutoEventWireup="true"
CodeBehind="AddNewCustomer.aspx.cs" Inherits=
"WebPage.AddNewCustomer" %>
<asp:Content ID="Content1" ContentPlaceHolderID=
"head" runat="server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID=
"contetnPlaceHolder" runat="server">
<asp:Label ID="Label1" runat="server" Text=
"Imię: "></asp:Label>
<asp:TextBox runat="server" ID="tbFistName">
</asp:TextBox>
<br />
<br />
<asp:Label runat="server" ID="Label2" Text=
"Nazwisko"></asp:Label>
<asp:TextBox runat="server" ID="tbLastName">
</asp:TextBox>
<br />
<br />
<asp:Button runat="server" ID="Submit" Text="Wyślij"/>
</asp:Content>
<%@ Page Title="" Language="C#" MasterPageFile=
"~/MasterPage.Master" AutoEventWireup="true"
CodeBehind="CustomerInfo.aspx.cs" Inherits=
"WebPage.CustomerInfo" %>
<asp:Content ID="Content1" ContentPlaceHolderID=
"head" runat="server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID=
"contetnPlaceHolder" runat="server">
<asp:Label ID="Label1" runat="server" Text="Id: ">
</asp:Label>
<asp:TextBox ID="TextBox1" runat="server"
ontextchanged="TextBox1_TextChanged">
</asp:TextBox>
<br />
<asp:Button ID="BShow" runat="server"
Text="Pokaż" />
<br />
<asp:Label ID="LId" runat="server"></asp:Label>
<br />
<asp:Label ID="LFirstName" runat="server">
</asp:Label>
<br />
<asp:Label ID="LLastName" runat="server">
</asp:Label>
<br />
</asp:Content>
<%@ Page Title="" Language="C#" MasterPageFile=
"~/MasterPage.Master" AutoEventWireup="true"
CodeBehind="AllCustomers.aspx.cs" Inherits=
"WebPage.AllCustomers" %>
<asp:Content ID="Content1" ContentPlaceHolderID=
"head" runat="server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID=
"contetnPlaceHolder" runat="server">
<asp:GridView ID="GridView1" runat="server">
</asp:GridView>
</asp:Content>
protected void Submit_Click(object sender,
EventArgs e) { MyService.Customer cust = new WebPage.MyService.Customer();
cust.FirstName = tbFistName.Text;
cust._lastName = tbLastName.Text;
MyService.CustomerServiceClient client = new WebPage.MyService.CustomerServiceClient();
client.AddNewCustomer(cust);
}
protected void BShow_Click(object sender,
EventArgs e) { MyService.CustomerServiceClient client = new WebPage.MyService.CustomerServiceClient();
MyService.Customer c = client.GetCustomerById(int.Parse(tbId.Text));LFirstName.Text = c.FirstName;
LLastName.Text = c._lastName;
LId.Text = c.ID.ToString();
}
protected void Page_Load(object sender,
EventArgs e) { MyService.CustomerServiceClient client = new WebPage.MyService.CustomerServiceClient();
GridView1.DataSource =
client.GetAllCustomers();
GridView1.DataBind();
}
Błąd jest spowodowany tym, że domyślnie nasz web serwis ma ustawione aby maksymalna paczka przesyłana do naszej aplikacji miała 64kb. Ponieważ w bazie jest duża ilość klientów, 64kb to trochę za mało aby ich wszystkich na raz przesłać. Istnieje kilka sposób na poradzenie sobie z tym problemem:
1. CustomPaging w GridView i pobieranie tylko wierszy o wskazanym Id
2. Zwiększenie maksymalnej wielkości przesyłanej od serwisu do naszej aplikacji.
Tutaj opiszę 2 możliwość, gdyż jest bezpośrednio związana z naszym web serwisem.
Klikamy prawym klawiszem na App.Config w web serwisie i wybieramy EditWCF configuration...
Przechodzimy do części Bindings, wybieramy New Binding Configuration...
Z listy wybieramy pasujący do naszego punktu końcowego format (wsHttpBinding)
Edytujemy kolejno wartości: MaxBufferPoolSize oraz MaxRecivedMessageSize. Zwiększymy obie wartości do np. 10 MB: 10485760:
Teraz dopisujemy konfigurację do naszego punktu końcowego:
Po tym zabiegu nasz serwis nadal nie będzie działać jeszcze poprawnie. Dzieje się tak dlatego, że wielkość paczki należy ustawić po obu stronach: klienta i serwera. Po stronie serwera mamy już sprawę załatwioną. Czas na klienta:
Tak jak poprzednio klikamy prawym klawiszem myszki na Web.Config i edytujemy właściwości WCF. Tutaj już jednak w Bindingu mamy na gotowe plik konfiguracyjny. Wystarczy tylko zwiększyć poprzednio pokazane wartości. Po zaakceptowaniu zmian możemy uruchomić ponownie nasz projekt.
Po ponownym odpaleniu projektu i wybraniu podstrony wyświetlającej wszystkich klientów otrzymamy ich całą listę:
Tak więc cel został osiągnięty :)
WinForms
1. Do projektu dodajemy nowy projekt WindowsForms.
2. Dodajemy TabControl do formatki:
3. Dodajemy kontrolki do każdej zakładki oraz referencję do serwisu:
4. Teraz do każdego przycisku odpowiedni kod (analogicznie jak dla wersji ASP.NET)
5. Zmieniamy wielkość przesyłanych danych do 10 MB po stronie klienta (plik app.config)
6. Kompilujemy i odpalamy naszą aplikację:
Jak widać tworzenie serwisów w WCF nie jest skomplikowane a niesie za sobą wiele korzyści. WCF jest bardzo elastyczną technologią i skazaną na swój rynkowy sukces.














