「お気軽メッセージハブ」ことポストTwitterとして一部で注目されているWassr(私のページ)ですが、
これのクライアントをWPFで制作しています。
WPFは数回触った程度なので、えむナウさんに突っ込まれたようにまだ理解できていない部分が多くありますが、
それでもWinFormsより圧倒的に生産性は高い気がします。
というかWinFormsで2は日でここまで作れません。(すごい人はできるかも)
画面は制作中のものであり実際の製品とは異なることがあります。
ButtonとTextBoxで構成されたNumericUpDownを作ったんだが、
どうもデータバインドが効いてないっぽい。
手動設定すれば動くんだが、何か規格違反があるのかな?
<UserControl x:Class="WasaWasa.Controls.NumericUpDown"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ws="clr-namespace:WasaWasa.Converters;assembly=WasaWasa.Converters"
MinWidth="50" MinHeight="20">
<UserControl.Resources>
<ws:IsDecimalRule x:Key="isDecimalRule"/>
<ws:DecimalRangeValidationRule x:Key="decimalRangeValidationRule"/>
</UserControl.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="16"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="16"/>
</Grid.ColumnDefinitions>
<Button Name="btnDown" Grid.Column="0" Margin="0">-</Button>
<TextBox Name="txtValue" Grid.Column="1" TextAlignment="Right" Margin="0">
<Binding x:Name="binding" Mode="TwoWay" Path="Value" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<StaticResource ResourceKey="isDecimalRule" />
<StaticResource ResourceKey="decimalRangeValidationRule" />
</Binding.ValidationRules>
</Binding>
</TextBox>
<Button Name="btnUp" Grid.Column="2" Margin="0">+</Button>
</Grid>
</UserControl>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.ComponentModel;
using WasaWasa.Converters;
namespace WasaWasa.Controls
{
/// <summary>
/// NumericUpDown.xaml の相互作用ロジック
/// </summary>
//TODO:MinValueとMaxValueとStepValueを依存プロパティ化する
public partial class NumericUpDown : UserControl, INotifyPropertyChanged
{
#region INotifyPropertyChanged メンバ
public event PropertyChangedEventHandler PropertyChanged;
#endregion
private static ValidationRule integerRule = new DecimalInInt32ValidationRule();
public static readonly DependencyProperty ValueProperty =
DependencyProperty.Register("Value", typeof(decimal), typeof(NumericUpDown),
new PropertyMetadata(new PropertyChangedCallback(delegate(DependencyObject p, DependencyPropertyChangedEventArgs e)
{
if ((p as NumericUpDown).PropertyChanged != null)
(p as NumericUpDown).PropertyChanged((p as NumericUpDown), new PropertyChangedEventArgs("Value"));
})));
public static readonly DependencyProperty IsIntegerOnlyProperty =
DependencyProperty.Register("IsIntegerOnly", typeof(bool), typeof(NumericUpDown),
new PropertyMetadata(new PropertyChangedCallback(delegate(DependencyObject p, DependencyPropertyChangedEventArgs e)
{
NumericUpDown ctrl = p as NumericUpDown;
bool value = (bool)e.NewValue;
bool oldValue = (bool)e.OldValue;
if (value)
{
if (oldValue)
return;
ctrl.AddValidationRule(NumericUpDown.integerRule);
}
else
{
if (!oldValue)
return;
ctrl.RemoveValidationRule(NumericUpDown.integerRule);
}
})));
public static readonly DependencyProperty MinValueProperty =
DependencyProperty.Register("MinValue", typeof(decimal), typeof(NumericUpDown),
new PropertyMetadata(decimal.MinValue, new PropertyChangedCallback(delegate(DependencyObject p, DependencyPropertyChangedEventArgs e)
{
((p as NumericUpDown).FindResource("decimalRangeValidationRule") as DecimalRangeValidationRule).MinValue = (decimal)e.NewValue;
if ((p as NumericUpDown).Value < (decimal)e.NewValue)
(p as NumericUpDown).Value = (decimal)e.NewValue;
})));
public static readonly DependencyProperty MaxValueProperty =
DependencyProperty.Register("MaxValue", typeof(decimal), typeof(NumericUpDown),
new PropertyMetadata(decimal.MaxValue, new PropertyChangedCallback(delegate(DependencyObject p, DependencyPropertyChangedEventArgs e)
{
((p as NumericUpDown).FindResource("decimalRangeValidationRule") as DecimalRangeValidationRule).MaxValue = (decimal)e.NewValue;
if ((p as NumericUpDown).Value > (decimal)e.NewValue)
(p as NumericUpDown).Value = (decimal)e.NewValue;
})));
public static readonly DependencyProperty StepValueProperty =
DependencyProperty.Register("StepValue", typeof(decimal), typeof(NumericUpDown),
new PropertyMetadata(1M), new ValidateValueCallback(delegate(object o)
{
return (decimal)o > 0;
}));
public bool IsIntegerOnly
{
get { return (bool)GetValue(IsIntegerOnlyProperty); }
set
{
SetValue(IsIntegerOnlyProperty, value);
PropertyChanged(this, new PropertyChangedEventArgs(ValueProperty.Name));
}
}
public decimal Value
{
get { return (decimal)GetValue(ValueProperty); }
set
{
if (value < MinValue)
value = MinValue;
if (MaxValue < MaxValue)
value = MinValue;
SetValue(ValueProperty, value);
}
}
public decimal MinValue
{
get { return (decimal)GetValue(MinValueProperty); }
set
{
SetValue(MinValueProperty, value);
}
}
public decimal MaxValue
{
get { return (decimal)GetValue(MaxValueProperty); }
set
{
SetValue(MinValueProperty, value);
}
}
public decimal StepValue
{
get { return (decimal)GetValue(StepValueProperty); }
set
{
SetValue(StepValueProperty, value);
}
}
public NumericUpDown()
{
InitializeComponent();
DataContext = this;
btnUp.Click += new RoutedEventHandler(delegate(object sender, RoutedEventArgs e)
{
Value += StepValue;
});
btnDown.Click += new RoutedEventHandler(delegate(object sender, RoutedEventArgs e)
{
Value -= StepValue;
});
}
public void AddValidationRule(ValidationRule rule)
{
binding.ValidationRules.Add(rule);
}
public void RemoveValidationRule(ValidationRule rule)
{
binding.ValidationRules.Remove(rule);
}
}
}
今WPFでWassrのクライアントを組んでるのですが、
設定画面の処理で、チェックボックスAにチェックがありかつチェックボックスBにチェックがない場合のみ有効にするという処理はどう書けばいいのでしょうか?
ソースが一つだけだったら分かるのですが、複数の場合はよく分かりません。
だれか教えてください。
適当に書いてみました。
Twitterを参考にはしていますが、独自の部分も多分に混じっています。
こんな機能があるといいとか、ここら辺がおかしいと思うものがあればコメントお願いします。
用語
- ミニブログもしくはメッセージハブとは、ステータスを登録し、時系列で取り出すことができるウェブサービスである。
- 発言もしくはステータスとは、投稿された発言のことである。
- 投稿もしくはアップデートとは、データベースにステータスを登録することである。
- タイムラインとは条件に一致したステータスを時系列で並べたものである。
- 購読もしくはフォローとは指定ユーザーのステータスを自身のフレンズタイムラインに含めることである。
- フォロワーとは自身をフォローするユーザーのことである。
- フレンドとは自身がフォローするユーザーのことである。
アクセス手段
- ミニブログはHTTPプロトコルを通じて(X)HTMLを返すウェブアプリケーションまたはRESTを含むAPIとしてアクセスすることができる。
- 標準のウェブインターフェイスは簡素な(X)HTMLを返すようにすべきである。
- REST APIは以下の形式を返すようにすべきである。
- APIへのアクセスはHTTPプロトコルで定義される方式に従って認証される。
一般的にはBasic認証もしくはDigest認証が使用される。 - ステータスの著作権は投稿したユーザー(以下投稿者)に帰属する。
ただし、規約として権利の行使を制限することができる。 - APIの呼び出しにより得られた結果は投稿者の著作権以外により利用が制限されない。
- APIのURLは自由に設定できる。
- すべてのAPIはWSDL(ウェブサービス定義言語)として一覧が提供されるべきである。
実装されるべきAPI
- APIで使用される構造体として以下のものが定義される。
また、構造体は自由に拡張でき、クライアントは対応していないプロパティは無視しなければならない。 - User
ユーザー - id:long
ID - name:string
内部名 - displayName:string
表示名 - profile:string
プロフィール - iconUrl:string
アイコン画像のURL - registeredDate:date
登録日時
- Status
ステータス - id:long
ID - userId:long
ユーザーID - postedDate:datetime
投稿日時 - text:string
本文 - source:string
クライアントの種類 - relatedUserId:long
関連付けられたユーザーのID - relatedStatusId:long
関連付けられたステータスのID
- OperationResult
実行結果 - succeed:boolean
成功/失敗 - statusCode:int
ステータスコード - statusMessage:string
ステータスの説明 - tag
付加的なデータ
- ユーザは以下のタイムラインをStatusオブジェクトの配列として取得できる。
また、各タイムラインを効率的に取得するための工夫がなされるべきである。 - Friends
自身と自身がフォローしたユーザーのステータス。 - User(Resent)
自身または指定ユーザーのステータス。 - Replies
自分または自分の発言に関連付けられたステータス。 - Favorates
自分または指定ユーザーがお気に入りに登録したステータス。 - Public
全ユーザーのステータス。
- ユーザーは以下の操作を実行できる。
- Update:OperationResult
ステータスを投稿する。
以下の引数を取り、また投稿されたステータスをtagとして返すべきである。 - text:string
本文 - [source:string]
クライアントの種類
- RemoveStatus:OperationResult
自身の投稿したステータスを削除する。
以下のステータスを取る。 - statusId:long
削除するステータスのID
- BookmarkStatus:OperationResult
ステータスをお気に入りに追加する
以下のステータスを取る。 - statusId:long
追加するステータスのID
- GetFollowedUsers:User[]
フォローしたユーザーの配列を取得する。
以下の引数を取る。 - [userId:long]
対象となるユーザーのID。
省略時は自身。
- GetFriends:User[]
フレンドの配列を取得する。
以下の引数を取る。 - [userId:long]
対象となるユーザーのID。
省略時は自身。
- GetFollowers:User[]
フォロワーの配列を取得する。
以下の引数を取る。 - [userId:long]
対象となるユーザーのID。
省略時は自身。
- FollowUser:OperationResult
ユーザーをフォローする。
以下のステータスを取る。 - {userId:long}
フォローするユーザーのID - {userName:string}
フォローするユーザーの内部名
- UnfollowUser:OperationResult
ユーザーのフォローを解除する。
以下のステータスを取る。 - {userId:long}
フォローするユーザーのID - {userName:string}
フォローするユーザーの内部名
- APIは既存のAPIに干渉しない範囲で拡張できる。
サムネイルから拡大画像へのリンクをページ遷移せずに開けるブックマークレットです。
ただし、途中にHTMLを挟んであるのはだめです。
- LB1
- LB2
使い方:
- LB1を実行し、ステータスバーを見ながら読み込み完了まで待つ。
- LB2を実行する。
- (゚д゚)ウマー
仕組み:
- LB1で本体のスクリプト(WbLightbox.js)を動的読み込みします。
- WbLightbox.jsからlightbox.jsとlightbox.cssを動的読み込みします。
- 手動で読み込み待機します。
- 画像へのリンクを捜し、lightbox.jsが認識できるようにします。
- lightbox.jsを初期化します。