visual C# 2010 Express を使用しています。
例えばWPFで新しいプロジェクトを立ち上げるとMainWindow.xamlがあって
そのウインドウの中にはGridが内装されていると思います。
そこで、UserControl1.xamlとUserControl2.xamlを追加して
最初はMainWindowのGridにはUserControl1を貼っておきます。
そしてMainWindowのボタンかなにかをクリックしたら
プログラムで動的にUserControl2に貼り替えたいのですが、
MainWindowクラス内でthis.(ここでプロパティやメンバを)候補を探しても
gridなどが見つからないのです・・・
どうやったら(なにで)動的にこのような切り替えをすることができるのでしょうか?
No.2ベストアンサー
- 回答日時:
VSのみだとVSMは使いにくい点も多いです。
なので,VSのみであるならば,コンバーター使って処理する方がお薦めになります。
> すいません、それとGridにはUserControl1が乗っているはずなのですが、
> プロパティやイベントを見てもUserControl1というのがないのですが(あればそこを切り替えれる)
> GridのどこにUserControl1はあるのでしょうか?
UserControlに名前をつけて下さい。
その名前で,Windowのフィールドとしてオブジェクトが存在します。
> クリックしたときに、ただユーザーコントロールの表示の切り替えをするのではなくて
> データベースを使った認証処理などプログラム的な処理も行いたいので、
> やはりなにかとコードから扱えた方が良いかと思うのですが、
> そこらへんもふくめて教えていただけないでしょうか?
このくらいだと,認証用ダイアログでMessangerやそれに似た機構を用意する必要があるくらいで,
あとはコードでUIを触る必要はなさそうです。
WinForms時代から,.NET FrameworkにはData Bindingという仕組みがあります。
さらに,WPFではCommand BindingやConverterといった仕組みが加わりました。
これらの仕組みによって,コードからUIを触る必要はそれほどなくなります。
例えば,
namespace WpfApplication1
{
public class Foo : System.ComponentModel.INotifyPropertyChanged
{
private bool _authorized = false;
private UserControl1ViewModel _uc1Model;
private UserControl2ViewModel _uc2Model;
public Foo ()
{
_uc1Model = new UserControl1ViewModel(this);
_uc2Model = new UserControl2ViewModel(this);
}
public bool Authorized
{
get { return _authorized; }
set
{
_authorized = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs("Authorized"));
PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs("NotAuthorized"));
}
}
}
public bool NotAuthorized { get { return !Authorized; } }
public UserControl1ViewModel ModelForUserControl1 { get { return _uc1Model; } }
public UserControl2ViewModel ModelForUserControl2 { get { return _uc2Model; } }
public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
}
}
なんてクラスがViewModelとしてあったとして,
<Window xmlns:local="clr-namespace:WpfApplication1">
<Window.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter1" />
</Window.Resources>
<Window.DataContext>
<local:Foo/>
</Window.DataContext>
<Grid>
<local:UserControl1 Visibility="{Binding Path=NotAuthorized, Converter={StaticResource BooleanToVisibilityConverter1}}" DataContext="{Binding ModelForUserControl1}" />
<local:UserControl2 Visibility="{Binding Path=Authorized, Converter={StaticResource BooleanToVisibilityConverter1}}" DataContext="{Binding ModelForUserControl2}" />
</Grid>
</Window>
のような記述をすれば,Foo.Authorizedの値の設定によってUserControl1とUserControl2の表示を切り替えられます。
# XAMLはだいぶ手抜きをしています。
ご回答ありがとうございます。
ユーザーコントロールに「x:Name="uc1" 」と付け加えたのですが
今回は見つけることができませんでした・・・一応ビルドもしてます。
コード的には
MainWindow.xaml.csのクラス内で
thisやthis.grid1から探してるのですが、見つかりません。。
VS的(?)には
フォームのプロパティがありますよね?
それのプロパティ、イベント両方でuc1というのがないのです・・・
具体的にどこを探せば良いのでしょうか?
それとすいません、具体的なコード示して頂きありがとうございます。
なんとなくこのプログラムのやりたいことは理解できるのですが、
つまりFoo.Authorizedの値の設定はボタンかなにかを用意して
それをクリックしたときに例えばloginButton_Click内で
Foo.Authorizedの値を設定すれば良いのでしょうか?
それともその値の設定すらなにかxaml側で自動で行ってくれるのでしょうか?
No.4
- 回答日時:
> で始めからuserControl11があったわけです。
とのことなので,
> <local:UserControl1 x:Name="uc1" ...
> は具体的にどこに記述すれば良いのでしょうか?
は不要です。
> ただ自分としてはgrid1の内容を切り替えたいので、
> this.grid1.(ここに例えばcontentsとか) = userControl12(新しいコントロール);
> のような感じでコード上で設定したいのですが、
> this.grid1のどのプロパティやメンバを探せば良いのでしょうか?
考え方を変えてみると良いと思います。
私の今までの回答の方針でもありますが,
「コントロールの表示状態を切り替える」ことができれば表示内容が切り替わります。
つまり,
userControl2.Visibility = Visibility.Visible;
userControl1.Visibliity = Visibility.Collapse;
とやれば,表示が切り替わります。
わざわざコントロールを動的に生成してGridに追加,とかする必要はありません。
# ここでもConverterとUIElement間でのBinding使うと,片方だけで済ますことは可能。
一応,
grid1.Children.Add(new UserControl2(...));
みたいにすれば,動的にコントロールを追加することは可能です。
ただ,その後に,結局コントロールの初期設定が必要なわけで,
それをするくらいならVisibilityの制御で済ます方が簡単だと思います。
ご回答ありがとうございます。
なるほど、Visibility を使って切り替えができました。
参考になりました。
あとはYune-Kichiさんが提示して頂いたコードを元に
自分なりに作ってみたいと思います。
コードも含めてとても参考になりました。
ありがとうございます。
No.3
- 回答日時:
> ユーザーコントロールに「x:Name="uc1" 」と付け加えたのですが
> 今回は見つけることができませんでした・・・一応ビルドもしてます。
ユーザーコントロールのインスタンスに名前をつけていますか?
先の例だと,
<local:UserControl1 x:Name="uc1" ...
のように書く必要あります。
> なんとなくこのプログラムのやりたいことは理解できるのですが、
> つまりFoo.Authorizedの値の設定はボタンかなにかを用意して
> それをクリックしたときに例えばloginButton_Click内で
> Foo.Authorizedの値を設定すれば良いのでしょうか?
そうなります。
ちなみに,突き詰めていくとButtonのClickイベントはICommand派生クラスをバインドさせることによって処理を委譲できるため,
ICommand.Executeの実装中でAutorizedの値を変更することになります。
で,RelayCommandなどの名前で呼ばれるICommand実装クラスは,デリゲートを指定することで自由にメソッドを指定できるようにします。
# RelayCommandとかDelegateCommandで探すと,似たような実装が山のように見つかると思います。
これらを使うと,UserControl1にバインドされたクラスのメソッドに実行をほぼ完全に委譲できます。
WPF/Silverlightでは,バインド機構を最大限活用する方が作りやすくなりますよ。
DataTemplateなど,バインド機構を前提としたものがたくさん存在します。
# 本質的には,表示自体のためだけのデータや動作以外を分離して,テスト等をやりやすくする為のものです。
WPF/Silverlightの標準的なパターンとなってきているMVVMというパターンも,
この強力なバインド機構が前提にあります。
example) MVVMもどき(末端のMがなかったり色々と……)
namespace WpfApplication1
{
using System.Windows.Input;
using System.ComponentModel;
public sealed class RelayCommand : ICommand
{
private readonly Action _execute;
private readonly Func<bool> _canExecute;
public RealyCommand (Action execute, Func<bool> canExecute)
{
_execute = execute;
_canExecute = canExecute;
}
public void Execute (object parameter) // そのコマンドを実行する
{
if (_execute != null) _execute();
}
public bool CanExecute (object parameter) // そのコマンドが実行可能かどうかの判定
{
// _executeが指定されていないなら常に実行不可
// _canExecuteが指定されていないなら常に実行可能
// どちらも指定されているなら_canExecuteに委譲
return _execute != null && (_canExecute == null || _canExecute());
}
public event EventHandler CanExecuteChanged {
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
}
public class UserControl1ViewModel : INotifyPropertyChanged
{
private string _loginName;
private string _password;
private readonly ICommand _login;
private readonly Foo _parent;
public UserControl1ViewModel () : this(null) { }
public UserControl1ViewModel (Foo parent)
{
_loginName = "";
_password = "";
_login = new RelayCommand(LoginImpl, CanLogin); // ログインボタンはCanLoginメソッドで処理自体の可否,LoginImplで実際の処理
_parent = parent;
}
// ログイン名
public string LoginName
{
get { return _loginName; }
set
{
_loginName = value ?? "";
if (PropertyChanged != null) PropertyChanged(new PropertyChangedEventArgs("LoginName"));
CommandManager.InvalidateRequerySuggested();
}
}
// パスワード
// System.Windows.Controls.PasswordBox.PasswordやSecurePasswordはDependencyPropertyではないのでバインド不可
// PasswordChangedイベントにトリガを仕掛けるか,素直にPasswordChangedイベントを処理する
public string Password
{
get { return _password; }
set
{
_password = value ?? "";
if (PropertyChanged != null) PropertyChanged(new PropertyChangedEventArgs("Password"));
CommandManager.InvalidateRequerySuggested();
}
}
// 以下,ログイン処理用
public ICommand Login { get{ return _login; } }
private void LoginImpl ()
{
// 実際のログイン処理 (ここでは省略)
_parent.Authorized = _loginName == "user" && _password == "pass";
}
private bool CanLogin ()
{
// ログインチェックへの条件
return _parent != null && !String.IsNullOrWhiteSpace(_loginName) && !String.IsNullOrWhiteSpace(_password);
}
}
}
// UserControl1.xaml
<UserControl xmlns:local="clr-namespace:WpfApplication1" d:DataContext="{x:Type local:UserControl1ViewModel}">
<Grid>
<Grid.RowDefinitions>
<Grid.RowDefinition />
<Grid.RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<Grid.ColumnDefinition />
<Grid.ColumnDefinition Width="auto" />
<Grid.ColumnDefinitions />
<TextBox Text="{Binding Path=LoginName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<TextBox Text="{Binding Path=Password, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Grid.Row="1" /> <!-- 面倒なのでPasswordBoxは使わない -->
<Button Content="ログイン" Command="{Binding Path=Login}" Grid.Column="1" Grid.RowSpan="2" />
</Grid>
</UserControl>
ご回答ありがとうございます。
なるほど、このプログラムもいいですね。
これから作る上で参考にさせてもらいます。
それとすいません、No2で
>thisやthis.grid1から探してるのですが、見つかりません。。
と言ったのですが、もともとthisからはuserControl11がありました・・・
this.userControl11
です。つまりMainWindow.xamlの中身は
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/pre …
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525" xmlns:my="clr-namespace:WpfApplication1">
<Grid x:Name="grid1">
<my:UserControl1 HorizontalAlignment="Left" Margin="188,78,0,0" x:Name="userControl11" VerticalAlignment="Top" Height="139" Width="184" />
</Grid>
</Window>
で始めからuserControl11があったわけです。
ただ自分としてはgrid1の内容を切り替えたいので、
this.grid1.(ここに例えばcontentsとか) = userControl12(新しいコントロール);
のような感じでコード上で設定したいのですが、
this.grid1のどのプロパティやメンバを探せば良いのでしょうか?
Yune-Kichiさんの仰る
<local:UserControl1 x:Name="uc1" ...
は具体的にどこに記述すれば良いのでしょうか?
No.1
- 回答日時:
Gridに名前をつけましたか。
<Grid x:Name="foo">
のように,名前をつけないと,コードから名前で扱うことは出来ません。
ただ,この場合だと,私の場合はVisualStateManagerで切り替えるか,
Boolean→VisibilityのValueConverter作ってそれぞれのVisiblityにバインドさせるなどによって,
表示に関してはコードから触らないようにしますが。
この回答への補足
すいません、それとGridにはUserControl1が乗っているはずなのですが、
プロパティやイベントを見てもUserControl1というのがないのですが(あればそこを切り替えれる)
GridのどこにUserControl1はあるのでしょうか?
ご回答ありがとうございます。
Gridの名前ですが、「x:」が抜けていたので付け加えたらコードで扱えました。
>VisualStateManagerで切り替えるか,
これはどのようにやるのでしょうか?
http://blogs.yahoo.co.jp/elku_simple/24926044.html
ここを参考に見てみたのですが、自分としては
クリックしたときに、ただユーザーコントロールの表示の切り替えをするのではなくて
データベースを使った認証処理などプログラム的な処理も行いたいので、
やはりなにかとコードから扱えた方が良いかと思うのですが、
そこらへんもふくめて教えていただけないでしょうか?
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Windows 7 ショートカットキー 応用編 どういうの主に使いますか? 2 2022/12/28 23:46
- VR・AR YoutubeでVRゴーグル用の切り替えボタンが表示されない? VRゴーグル(中にスマホを入れるタイ 3 2022/10/20 10:27
- HTML・CSS CSSのホバーエフェクト 1 2023/06/19 06:53
- デジタルカメラ sony a7ii と 富士フイルムX-T2について 【sony a7ii】 数値変動・動画ボタンの 1 2023/03/21 01:14
- その他(コンピューター・テクノロジー) Pythonの np.indicesに関する質問です。 2 2023/02/07 08:19
- その他(ソフトウェア) ジャストシステムのATOKについて 1 2023/03/18 14:24
- ノートパソコン サーフェスというノートパソコンを 6年ほど使っています。 パソコンに無知で、音声について教えて頂きた 1 2023/04/17 08:06
- Chrome(クローム) グーグルクロムをマイクロソフト・エッジに切り替える方法 2 2022/06/20 10:08
- Wi-Fi・無線LAN ノートパソコンのWiFiとLANケーブルの切り替えは自動なのでしょうか 普段zoomをWiFiでつな 7 2023/02/01 17:11
- テレビ テレビはSONYブラビアKDL-55W900Aです。 1週間程テレビを見ずにYOUTUBEばかりを見 4 2023/03/24 01:25
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・【大喜利】【投稿~11/22】このサンタクロースは偽物だと気付いた理由とは?
- ・お風呂の温度、何℃にしてますか?
- ・とっておきの「まかない飯」を教えて下さい!
- ・2024年のうちにやっておきたいこと、ここで宣言しませんか?
- ・いけず言葉しりとり
- ・土曜の昼、学校帰りの昼メシの思い出
- ・忘れられない激○○料理
- ・あなたにとってのゴールデンタイムはいつですか?
- ・とっておきの「夜食」教えて下さい
- ・これまでで一番「情けなかったとき」はいつですか?
- ・プリン+醤油=ウニみたいな組み合わせメニューを教えて!
- ・タイムマシーンがあったら、過去と未来どちらに行く?
- ・遅刻の「言い訳」選手権
- ・好きな和訳タイトルを教えてください
- ・うちのカレーにはこれが入ってる!って食材ありますか?
- ・おすすめのモーニング・朝食メニューを教えて!
- ・「覚え間違い」を教えてください!
- ・とっておきの手土産を教えて
- ・「平成」を感じるもの
- ・秘密基地、どこに作った?
- ・【お題】NEW演歌
- ・カンパ〜イ!←最初の1杯目、なに頼む?
- ・一回も披露したことのない豆知識
- ・これ何て呼びますか
- ・初めて自分の家と他人の家が違う、と意識した時
- ・「これはヤバかったな」という遅刻エピソード
- ・これ何て呼びますか Part2
- ・許せない心理テスト
- ・この人頭いいなと思ったエピソード
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・好きなおでんの具材ドラフト会議しましょう
- ・餃子を食べるとき、何をつけますか?
- ・あなたの「必」の書き順を教えてください
- ・ギリギリ行けるお一人様のライン
- ・10代と話して驚いたこと
- ・大人になっても苦手な食べ物、ありますか?
- ・14歳の自分に衝撃の事実を告げてください
- ・家・車以外で、人生で一番奮発した買い物
- ・人生最悪の忘れ物
- ・あなたの習慣について教えてください!!
- ・都道府県穴埋めゲーム
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
大量のデータを読み込んで表示...
-
StrutsのiterateタグでListに格...
-
C# WinForm のDataGridView Cel...
-
C#で、あるクラスのメンバーす...
-
Processingでマウスクリックで...
-
Junitテストでvoid戻り値メッソ...
-
LVM_SETITEMSTATEでListViewの...
-
決められて時間が経過するとア...
-
Thread.sleepのInterruptedExce...
-
C#で別のFormへ複数の値を返そ...
-
java アプリケーションをjava ...
-
Runtime#proccessのwait
-
C# DataGridView列カスタマイズ
-
C# visibleプロパティをfalseに...
-
javaアプレット repaintのタイ...
-
C#でキーイベントが発生しない...
-
C# MouseHoverを何度も呼ぶには
-
MouseEventのつけ方
-
JScrollPaneで、表示がおかしく...
-
変数を動的に利用するには?
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
大量のデータを読み込んで表示...
-
C#で、あるクラスのメンバーす...
-
Junitテストでvoid戻り値メッソ...
-
C#でのWNetAddConnection3の使...
-
C# 矢印キーの取得
-
ボタンの複数割り当てについて
-
C# DataGridView列カスタマイズ
-
コンボボックスを使う時の警告
-
ユーザーコントロールを動的に...
-
アプレットでマウスイベントが...
-
C#で別のFormへ複数の値を返そ...
-
LVM_SETITEMSTATEでListViewの...
-
C#,listBoxのItem追加について...
-
C# MouseHoverを何度も呼ぶには
-
C# visibleプロパティをfalseに...
-
C# 親フォームで指定した値を...
-
C# 半角カナの文字化けについて
-
決められて時間が経過するとア...
-
javaを用いて,a列,b列の空白...
-
Processingでマウスクリックで...
おすすめ情報