get the solution

Blog

Seite: 1


Simon Simon
11.03.2010 20:34

Netgear ReadyNAS - RewriteRules einrichten



Wenn man beim ReadyNAS Duo von Netgear in seinem eigenen /www Verzeichnis eine .htaccess Datei mit RewriteRules hat , bekommt man einen 403 Forbidden Fehler.
Der Fehlerlogbericht zeigt folgendes:

[Thu Mar 11 10:27:41 2010] [error] [client 194.xxx.xxx.xx] Options FollowSymLinks or SymLinksIfOwnerMatch is off which implies that RewriteRule directive is forbidden: /c/www/projects/xxxx/index-1-1, referer: http://.........
 
Dieser Fehler lässt sich sehr einfach beheben, indem man die Optionen "FollowSymLinks" und "SymLinksIfOwnerMatch" in der /etc/frontview/apache/Shares.conf bei der <Location /www> Sektion einfügt.

Die Datei wird gespeichert und der Frontview neugestartet. Doch die Änderungen scheinen keine Auswirkung zu haben! Den der Readynas überschreibt die Konfiguration beim neustarten jedes mal neu. An diesem Problem riss ich mir die Haare aus. Das initscript gab keine Hinweise und bis jetzt habe ich auch keine Idee, warum diese Datei ständig zurückgesetzt wird.

Die Lösung ist dennoch trivial: Man kopiert einfach die <Location /www> Sektion inklusive (!) Alias Anweisung für den /www-Bereich in die /etc/frontview/apache/httpd.conf. Das sieht dann so aus:
 
Alias /www /c/www
	<Location "/www">
	  Options Indexes FollowSymLinks SymLinksIfOwnerMatch
	  Order allow,deny
	  Allow from all
	</Location>

Danach funktioniert alles einwandfrei. Welche Idee oder Logik hinter diesem "Konfigurationsdateien-Zurücksetzen" Prinzip steckt, kann ich mir nicht erklären. Auch fand ich im Internet keine Lösungen zu diesem Problem.

Verwandte Themen:
Netgear - ReadyNAS Duo

Schlüsselwörter: readynas netgear duo apache rewrite rules forbidden 403 FollowSymLinks
zuletzt geändert: 12. März 2010 14:17
Link zu diesem Artikel: (in die Zwischenablage)
Kommentare: Anzeigen




Martin Martin
14.02.2010 18:24

Tray Icon mit WPF



Es gibt mir zwei bekannte möglichkeiten ein Tray Icon mit WPF zu realisieren. Die erste ist man erstellt ein WPF Window und erstellt darin, das Tray Icon Objekt. Meiner Meinung nach ist das aber der falsche Weg. Darin wird nur das Tray Icon Objekt gehostet. Die Nachteile:

  • Code ist nicht gut getrennt Tray Icon / Window
  • Will man nur das Tray Icon zum Programmstart anzeigen muss das Fenster versteckt werden
Die zweite, meiner Meinung nach, richtige Lösung wäre, in der App.xaml.cs Datei die Methode OnStartup zu überschreiben und von dort aus das Tray Icon Objekt zu erstellen. Nun kann man beliebig viele Fenster über das Tray Icon erstellen.


Das ganze realisiert man so:

  1. Projekttyp "Neue WPF Anwendung" erstellen
  2. Das vorhandene Window kann man wie man will löschen oder stehen lassen, wenn man dieses später benötigt
  3. In der App.xaml entfernen wir den Eintrag StartupUri="Window1.xaml"
  4. Damit verhindern wir, dass beim Programmstart das Fenster Window1 erstellt und angezeigt wird.
  5. Für das TrayIcon verwenden wir das Objekt NotifyIcon welches sich in der Libary System.Windows.Forms befindet.
  6. Wir fügen also zu den Verweisen ->Rechter Mausklick -> Verweis hinzufügen -> System.Windows.Forms und System.Drawing hinzu damit wir auch das Icon setzen können

Ich habe eine kleine Tray Icon Klasse geschrieben, damit man schnell ein paar ContextMenu einträge zum Tray Icon hinzufügen kann. Dazu erstellen wir uns eine neue Klassen-Datei namens Tray.cs und fügen folgenden Code ein.

using System.Windows.Forms;
	using System;
	 
	public class Tray
	{
	    private NotifyIcon _notico;
	    private bool _Animate = false;
	    private ContextMenu _contextMenu = new ContextMenu();
	 
	    public Tray()
	    {
	        Initialize();
	    }
	    public Tray(System.Drawing.Icon pIcon)
	    {
	        Initialize();
	        _notico.Icon = pIcon;
	    }
	    /// <summary>
	    /// Initialisiert das NotifyIcon
	    /// </summary>
	    private void Initialize()
	    {
	        // NotifyIcon erzeugen
	        _notico = new NotifyIcon();
	        _notico.Visible = true;
	 
	        ContextMenu contextMenu = new ContextMenu();
	 
	        // Kontextmenüeinträge erzeugen
	 
	        _notico.ContextMenu = _contextMenu;
	 
	    }
	    public void CreateMenuItem(String pName)
	    {
	        MenuItem menuItem = new MenuItem();
	        menuItem = new MenuItem();
	        menuItem.Index = 1;
	        menuItem.Name = pName;
	        menuItem.Text = "&" + menuItem.Name;
	 
	        _contextMenu.MenuItems.Add(menuItem);
	    }
	    public void CreateMenuItem(String pName, bool pTrue)
	    {
	        MenuItem menuItem = new MenuItem();
	        menuItem.Index = 2;
	        menuItem.Name = pName;
	        menuItem.Text = "&" + menuItem.Name;
	        menuItem.Click += (sender, e) =>
	        {
	            MenuItem m = (MenuItem)sender;
	            m.Checked = !m.Checked;
	        };
	        menuItem.Checked = pTrue;
	 
	        _contextMenu.MenuItems.Add(menuItem);
	    }
	    public NotifyIcon NotifyIcon
	    {
	        get
	        {
	            return _notico;
	        }
	    }
	}
	

Jetzt öffnen wir die App.xaml.cs Datei und überschreiben die Methode OnStartUp(). 

Damit unser Programm nicht beendet wird, wenn man ein erstelltes Fenster schließt, müssen wir die Propertie ShutdownMode neu setzen.

In der MSDN steht dazu folgendes.

"Ruft die Bedingung ab, unter der die Shutdown-Methode aufgerufen wird, oder legt diese fest."

Wir setzen die Propertie deshalb auf den Wert  OnExplicitShutdown.

Damit das Tray Icon im Tray überhaupt sichtbar ist, benötigen wir ein Icon. Man kann ein neues Icon direkt im Vs.net erstellen oder ein vorhandenes hinzufügen. Wie man das Icon ins Programm ladet bleibt jedem selber überlassen. Ich lade das Icon einfachhalts halber aus einer Datei.

Danach erstellen wir das Tray Objekt und übergen das Icon welches, wir aus der Datei geladen haben.

Nun können wir, auf die Tray Methoden zugreifen und beliebig viele ContextMenüs erstellen.

Über die Propertie NotifyIcon der Klasse Tray können wir auf die MenüItems zugreifen und deren verhalten bestimmen. Z.b, wenn man auf ein Menüitem Klickt, dass ein neues Fenster erstellt wird, oder dass die komplette Applikation mit samt Tray Icon geschlossen wird.

Das sieht dann so aus:

using System;
	using System.Collections.Generic;
	using System.Configuration;
	using System.Data;
	using System.Linq;
	using System.Windows;
	using System.Drawing;
	 
	namespace Tray_Icon_WPF
	{
	    /// <summary>
	    /// Interaction logic for App.xaml
	    /// </summary>
	    public partial class App : Application
	    {
	        protected override void OnStartup(StartupEventArgs e)
	        {
	            this.ShutdownMode = ShutdownMode.OnExplicitShutdown;
	 
	            //Icon laden
	            Icon icon = Icon.ExtractAssociatedIcon(@"C:UsersmartinDocumentsVisual Studio 2008BlogTray Icon WPFTray Icon WPFIcon1.ico"); 
	 
	            //trayicon erstellen und icon laden
	            Tray tray = new Tray(icon);
	 
	            tray.CreateMenuItem("Fenster aufrufen");
	            tray.CreateMenuItem("Beenden");
	 
	            //Menuitem Fenster aufrufen suchen, zugreifen Click Event anmelden und delegate setzen
	            tray.NotifyIcon.ContextMenu.MenuItems.Find("Fenster aufrufen", true).First().Click += (sender, eargs) =>
	            {
	                Window1 window = new Window1();
	                window.Show();
	 
	            };
	 
	            //Menuitem Beenden suchen, zugreifen Click Event anmelden und delegate setzen
	            tray.NotifyIcon.ContextMenu.MenuItems.Find("Beenden", true).First().Click += (sender, eargs) =>
	            {
	                //Icon aus tray löschen
	                tray.NotifyIcon.Dispose();
	                Environment.Exit(0);
	            };
	 
	 
	            base.OnStartup(e);
	        }
	    }
	}

Das Demo Projekt ist im Anhang. Wenn ihr die Demo ausführt, müsst ihr den Pfad zum Icon anpassen. Über Fragen, Anregungen, Kritik freu ich mich.

Links:
Guter Artikel über das Tray Icon, allerdings wird der ShutdownMode nicht erwähnt
http://www.codecomplete.de/blogs/xamlblog/archive/2008/12/15/wpfanwendung-mit-trayicon.aspx 
So sollte es meiner Meinung nicht machen (Code im Window)
http://possemeeg.wordpress.com/2007/09/06/minimize-to-tray-icon-in-wpf/



Schlüsselwörter: WPF
zuletzt geändert: 14. Feber 2010 19:38
Link zu diesem Artikel: (in die Zwischenablage)
Kommentare: Anzeigen




Martin Martin
10.12.2009 12:03

Filter Data mit MVVM (Filtering ListView, ListBox mit MVVM)



In diesem Eintrag zeige ich, wie man in WPF Daten (IList<T>) mit dem MVVM Pattern filtern kann.
Ich habe darauf geachtet, dass man möglichst individuell bestimmen kann wie Daten gefiltert werden können. Natürlich gibt es noch andere Möglichkeiten Listen zu filtern (CollectionView) die ihre Vor- und Nachteile gegenüber dieser Methode haben. Seht selbst ob sie euch gefällt.

Im Prinzip ist dieser Lösungsvorschlag relativ einfach zu realisieren. Im ViewModel hat man wie üblich die Liste mit den Daten auf die eine ListBox, ListView... bindet. Wenn wir nun aber die Liste filtern wollen, benötigen wir zusätzlich eine weitere Liste in dem nur die gefilterten Daten gespeichert sind. Das Control zum Anzeigen der Daten bindet nun auf die Gefilterte Liste mit den Daten und nicht mehr auf die orginal Liste. Die gefilterte Liste macht folgendes.
 
Sie führt eine Linq Abfrage auf die Original Liste aus. Zu dieser Linq Abfrage fügt man sämtliche Bedinungen ein die dem Filter entsprechen. Schlussendlich wird aus der Linq Abfrage die gefilterte Liste erstellt, welche dann eine ListBox, ListView… anzeigt.

Um diese Vorgehensweise besser veranschaulichen zu können habe ich ein Beispiel erstellt. In diesem Beispiel sollen sämtliche Produkte eines Geschäftes angezeigt werden. Damit der Kunde eine bessere Übersicht über die Produkte hat, soll man einen Filter hinzufügen.
 
Einmal soll der Kunde nach Produkten suchen können und diese auch nach dem Preis und dem Attribut Ausverkauft filtern können.
Unser Produkt hat die Eigenschaften Name, Preis, Ausverkauft.
 
In Unserem ViewModel haben wir einmal die Liste mit den Orginal Daten (ProduktList) und eine Liste welche nur die Gefilterten Daten zurück gibt (FilteredList). Zusätzlich haben wir noch pro Filter eine Propertie die den Filter representiert. Also FilterAusverkauft, FilterName zum nach Produkten suchen zu können und FilterPreis um nur Produkte mit einem bestimmten Preis an zu zeigen.

 
ref

 
Zuerst der XAML Code. Die Oberfläche zeigt einmal eine ListView an, in der die gefilterten Produkte je nach Filter Einstellung angezeigt werden. Die ListView bindet auf die Gefilterte Liste vom ViewModel. Zusätzlich hat der Benutzer die Möglickeit die Filter mittels TextBox, CheckBox zu setzen.

	            <GroupBox Header="Filter" DockPanel.Dock="Top">
	                <StackPanel Orientation="Horizontal">
	                    <!-- Hier kann man die Filter aktivieren -->
	                    <TextBlock Text="Name" VerticalAlignment="Top" />
	                    <TextBox Text="{Binding Path=FilterName,UpdateSourceTrigger=PropertyChanged}"/>
	                    <TextBlock Text="Preis" VerticalAlignment="Top" />
	                    <TextBox Text="{Binding Path=FilterPreis,UpdateSourceTrigger=PropertyChanged}"/>
	                    <TextBlock Text="Ausverkauft" VerticalAlignment="Top" />
	                    <CheckBox IsChecked ="{Binding Path=FilterAusverkauft,UpdateSourceTrigger=PropertyChanged}"/>
	                </StackPanel>
	            </GroupBox>
	            <!-- Daten anzeigen -->
	            <ListView ItemsSource="{Binding Path=FilteredList,UpdateSourceTrigger=PropertyChanged}" DockPanel.Dock="Top">
	                <ListView.View>
	                    <GridView>
	                        <GridViewColumn Header="Name" DisplayMemberBinding="{Binding Name}"></GridViewColumn>
	                        <GridViewColumn Header="Preis" DisplayMemberBinding="{Binding Preis}"></GridViewColumn>
	                        <GridViewColumn Header="Ausverkauft" DisplayMemberBinding="{Binding Ausverkauft}"></GridViewColumn>
	                    </GridView>
	                </ListView.View>
	            </ListView>

Wichtig ist, dass man bei den Filter Properties beim Binding ein UpdateSourceTrigger=PropertyChanged an gibt. Dann werden sämtliche aktualisierungen sofort weiter gegeben. Wenn jetzt jemand beim Filter Name einen Buchstaben eingibt, wird sofort die GefilterteListe erneuert.

	        public string FilterName
	        {
	            get
	            {
	                return _FilterName;
	            }
	            set
	            {
	                _FilterName = value;
	                NotifyPropertyChanged("FilterName");
	                NotifyPropertyChanged("FilteredList");
	            }
	        }
 
Beim Propertie FilterName wird zusätzlich die Methode NotifyPropertyChanged("FilteredList") ausgeführt. Was zur Folge hat, dass die ListView sich nochmal die Daten von der Propertie FiltedList holt.

	        public ObservableCollection<Produkt> FilteredList
	        {
	            get
	            {
	                return GetFilteredList(ProduktList);
	            }
	        }

Dabei wird unsere GetFiltedList Methode aufgerufen. Dieser übergeben wir die orginal Liste. Diese führt die Linq Abfrage aus und erstellt uns eine neue gefilterte Liste.

	        private ObservableCollection<Produkt> GetFilteredList(ObservableCollection<Produkt> pOrginalProduktList)
	        {
	            ObservableCollection<Produkt> filteredproduktlist = new ObservableCollection<Produkt>();
	 
	            var x = from p in pOrginalProduktList
	                    where
	                        FilterNameMethod(p, this.FilterName) &&
	                        FilterAusverkauftMethod(p, this.FilterAusverkauft) &&
	                        FilterPreisMethod(p, this.FilterPreis)
	                    select p;
	 
	            foreach (var u in x)
	                filteredproduktlist.Add(u);
	 
	            return filteredproduktlist;
	        }

Der Linq Abfrage übergeben wir unsere Bedingungs Methoden FilterNameMethode, FilterAusverkauftMethode, FilterPreisMethode. In dieser können wir selbst bestimmen wie wir was überprüfen. Schauen wir uns dazu die FilterNameMethode etwas genauer an.

	        public static bool FilterNameMethod(Produkt pProdukt, string pName)
	        {
	            if (pProdukt == null) return false;
	            if (pName == null) return false;
	            if (pName.Equals(string.Empty)) return true;
	            return (pProdukt.Name.ToUpper().StartsWith(pName.ToUpper()));
	        }

Die Bedinungsmethode muss immer einen Boolean zurückgeben. Sinnvoll ist es auch, das gerade itterierende Item der Linq Abfrage der Methode zu übergen. Als zweiten Parameter übergeben wir die FilterName Propertie. Damit können wir die Linq Abfrage beeinflussen.

In der dritten if Bedinung wird überprüft ob pName (=FilterName) leer ist. Wir geben hier true zurück. Das Element soll also in die gefilterte Liste hinzugefügt werden, da der Filter nicht aktiv scheint. Erst wenn jemand in die Propertie Filtername bzw. in pName etwas hineinschreibt soll je nach dem, wenn der Anfangsbuchstabe passt, das gerade itterierende Item zur gefilterten Liste hinzugefügt werden.

Die Vorgangsweise bei den anderen Filter Methoden ist die gleiche. Statt einer String Überprüfung wird ein int oder bool Wert geprüft. Soll das Item in die gefilterte Liste aufgenommen werden gibt die Filter Methode true zurück andern falls false.

Will man ein Element Manipulieren, löschen, duplizieren etc. muss man die Änderungen immer an der Orginal Liste durchführen. Wichig dabei ist, dass nach der Änderung ein NotifyPropertyChanged("FilterList") ausgeführt wird, damit die FiltedList neu erstellt wird.

Ich denke, dass man dieses Filter Prinzip relativ einfach umsetzen kann. Bei unklarheiten, ergänzungen schreibt mir ein Comment. Das gesamte Projekt kann vom Anhang heruntergeladen werden.



Beispielprojekt Download:

 

kick it on dotnet-kicks.de

Schlüsselwörter: WPF, XAML, LINQ
zuletzt geändert: 11. Dezember 2009 16:35
Link zu diesem Artikel: (in die Zwischenablage)
Kommentare: Anzeigen




Simon Simon
19.11.2009 19:24

Probleme mit php-gettext



Vor kurzem wurde bei einem unserer Hoster eine PHP-Aktualisierung vorgenommen. Diese führte dazu, dass auf sämtlichen Webseiten nur noch die englische Sprache angezeigt wurde. Der Grund dafür war eine Änderungen bezüglich der Byteorder in PHP.
Die von uns eingesetzte Übersetzungs-Engine php-gettext hatte noch keinen Patch für diesen "Fehler".

Um den Fehler zu beheben muss man in der Datei gettext.php Zeile 117 den Code von:

$this->error = 1; // not MO file
	
auf

$this->BYTEORDER = 0; /* change this line */
	
abändern.

Das Code-Fragment sieht dann so aus:

	    $this->STREAM = $Reader;
	    $magic = $this->readint();
	    if ($magic == $MAGIC1) {
	      $this->BYTEORDER = 0;
	    } elseif ($magic == $MAGIC2) {
	      $this->BYTEORDER = 1;
	    } else {
	      $this->BYTEORDER = 0; /* change this line */ 
	      return false;
	    }
	
Homepage des Projekts: http://savannah.nongnu.org/projects/php-gettext/

Bugreport auf Savannah



Schlüsselwörter: php-gettext, no translations, PHP 5.2.11
zuletzt geändert: 19. November 2009 23:28
Link zu diesem Artikel: (in die Zwischenablage)
Kommentare: Anzeigen




Martin Martin
22.10.2009 16:02

ColorAnimation im XAML vs ColorAnimation im C# Code



Vorgeschichte:

CoffeClock ist ein Erinnerungsprogram. Wenn man gerade etwas auf dem Herd hat, und nebenbei am Computer sitzt kommt es schnell vor, dass man alles um sich herum vergisst. Bei mir ist das jedenfalls so. So kam es schon öfter vor, dass einige Leckerein verbrannten. Um dieses Problem vor zu beugen habe ich dieses Erinnerungsprogramm geschrieben.

Man gibt den Erinnerungstext und die Zeit ein, wann man an etwas Erinnert werden soll. Danach versteckt sich das Programm und wartet im Hintergrund bis die Zeit abgelaufen ist. Wenn die Zeit abgelaufen ist wird der Komplette Bilschirm schwarz und der Erinnerungstext wird weiß eingeblendet.

Wenn man die ESC Taste drückt, soll das Erinnerungsprogramm beendet werden und man kehrt zum Desktop zurück.

Die Animation:

Jetzt wär es cool wenn man das Zurückkehren zum Desktop mittels einer Animation machen könnte. Von Schwarz überlaufend in den Desktop (bzw. von Schwarz in Transparent).

Animationen habe ich bis jetzt immer im XAML erstellt. Also wollte ich das auch in diesem Fall so machen. Das hätte dann so ausgesehen:

<Window.Triggers>
	        <EventTrigger RoutedEvent="Window.PreviewKeyDown">
	            <BeginStoryboard>
	                <Storyboard>
	                    <ColorAnimation Storyboard.TargetProperty="Background.Color" 
	From="Black" To="Transparent" Duration="00:00:01.000" />
	                </Storyboard>
	            </BeginStoryboard>
	        </EventTrigger>
	    </Window.Triggers>

Tja, leider kam mir keine Idee, wie ich im XAML abfragen kann ob der Benutzer die ESC Taste gedrückt hat. Hinzu kommt, dass ich nach der Animation das Programm beenden muss. In XAML wäre das wahrscheinlich ebenso schwer bis gar unmöglich zu realisieren.

Also musste ich die Animation doch im C# Code erstellen.

Mein erster geh versuch sah so aus (der C# Animationscode sollte equivalent zum XAML Code sein):

	            ColorAnimation colorAnimation = new ColorAnimation();
	            colorAnimation.Duration = new Duration(new TimeSpan(0, 0, 10));
	            colorAnimation.From = Colors.Black;
	            colorAnimation.To = Colors.Transparent;
	 
	            this.BeginAnimation(Window.BackgroundProperty, colorAnimation);
Mit diesem Code erhielt ich die Exception:

"AnimationTimeline" vom Typ "System.Windows.Media.Animation.ColorAnimation" kann nicht zum Animieren der Background-Eigenschaft vom Typ "System.Windows.Media.Brush" verwendet werden.
Parametername: animation

Beim näheren betrachten sieht man auch, dass man im XAML als TargetPropertie Background.Color angegeben hat. Leider kann man das im C# Code so nicht setzen, da man mit Window.BackgroundProperty nur auf die Properties des DependencyProperties zugreifen kann.

Die Lösung ist eine Referenz auf den Background Brush. Das sieht dann so aus:

	            Brush backgroundBrush = this.Background;
	            backgroundBrush.BeginAnimation(SolidColorBrush.ColorProperty, colorAnimation);
Nach der Animation habe ich dann den Befehl this.Close()  ausgeführt.

Jetzt stand ich vor dem nächsten Problem. Die Animation wird asynchron ausgeführt. Das heißt man sieht die Animation gar nicht, da sofort das Fenster geschlossen wird.

Zum glück hat die Klasse ColorAnimation ein Event Completed welches, wie der Name bereits verrät, gefeuert wird, wenn die Animation fertig ist.

Ich habe den Close() Befehl also in das Event Completed gesteckt. Nun wird, nach dem drücken der Taste ESC zuerst die Animation abgespielt und zu guter letzt das Programm beendet.

Der komplette und richtige Code sieht so aus:

this.PreviewKeyDown += (sender, e) =>
	            {
	                if (e.Key.Equals(Key.Escape))
	                {
	                    ColorAnimation ani = new ColorAnimation(Colors.Transparent, new Duration(new TimeSpan(0, 0, 0, 1, 0)));
	                    ani.Completed += (Completedsender, Completede) =>
	                    {
	                        this.Close();
	                    };
	 
	                    SolidColorBrush newBrush = new SolidColorBrush(Colors.Black);
	 
	                    this.Background = newBrush;
	 
	                    newBrush.BeginAnimation(SolidColorBrush.ColorProperty, ani);
	                }
	            };
Ein großes Dank geht an talla vom mycsharp Forum der mir bei meinen Animationsproblemen weiter geholfen hat.

Links:
http://msdn.microsoft.com/de-de/library/system.windows.media.animation.coloranimation.aspx

Das Erinnerungsprogramm CoffeeClock können Sie hier herunterladen ( benötigt .NET 3.5 7Kb groß):

Zum Download

Schlüsselwörter: XAML, WPF, Get
zuletzt geändert: 22. Oktober 2009 21:32
Link zu diesem Artikel: (in die Zwischenablage)
Kommentare: Anzeigen




Seite: 1



(c) 2003-2009 | Impressum| Empfehlenswerte Blog Einträge