質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

WPF

Windows Presentation Foundation (WPF) は、魅力的な外観のユーザー エクスペリエンスを持つ Windows クライアント アプリケーションを作成するための次世代プレゼンテーション システムです

Q&A

解決済

2回答

952閲覧

WPF コンテキストメニューを開いた場所のTextBlockを編集できるようにしたい

kiyure

総合スコア13

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

WPF

Windows Presentation Foundation (WPF) は、魅力的な外観のユーザー エクスペリエンスを持つ Windows クライアント アプリケーションを作成するための次世代プレゼンテーション システムです

0グッド

1クリップ

投稿2019/01/14 13:32

編集2019/01/15 23:29

前提・実現したいこと

(無知なため、誤った用語の使い方をしていたら申し訳ありません。)

現在、練習も兼ねて自分用で某ゲームの簡単な補助ツールを制作しています。
エンドユーザ側で編集を行いたいTextBlockを沢山配置するため、コンテキストメニューから、何らかの方法でクリックした部分にあるTextBlockを編集できるようにする方法を教えていただきたいです。
また、可能であれば時刻の記録や計算も行いたいため、そういった物も同様に扱える方法が望ましいです。
「多少操作方法が変わるが、容易に実装できる」といった方法でも構いません。
よろしくお願いします。

該当のソースコード

MainWindow.xaml

<Window x:Class="Kuro.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:Kuro" mc:Ignorable="d" Title="MainWindow" Height="450" Width="800"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition/> </Grid.ColumnDefinitions> <TextBlock HorizontalAlignment="Left" Margin="120,10,0,0" TextWrapping="Wrap" Text="Sun" VerticalAlignment="Top"/> <Grid HorizontalAlignment="Left" Height="18" Margin="80,30,0,0" VerticalAlignment="Top" Width="100"> <Border BorderBrush="Black" BorderThickness="1" HorizontalAlignment="Left" Height="18" VerticalAlignment="Top" Width="100"> <Border.ContextMenu> <ContextMenu> <MenuItem Header="キャラ名編集" Click="CName_Edit"/> </ContextMenu> </Border.ContextMenu> <TextBlock TextWrapping="Wrap" x:Name="Chara1" Text="キャラ1" HorizontalAlignment="Center"/> </Border> </Grid> <TextBlock HorizontalAlignment="Left" Margin="228,10,0,0" TextWrapping="Wrap" Text="Mon" VerticalAlignment="Top"/> <Grid HorizontalAlignment="Left" Height="18" Margin="190,30,0,0" VerticalAlignment="Top" Width="100"> <Border BorderBrush="Black" BorderThickness="1" HorizontalAlignment="Left" Height="18" VerticalAlignment="Top" Width="100"> <Border.ContextMenu> <ContextMenu> <MenuItem Header="キャラ名編集" Click="CName_Edit"/> </ContextMenu> </Border.ContextMenu> <TextBlock TextWrapping="Wrap" x:Name="Chara2" Text="キャラ2" HorizontalAlignment="Center"/> </Border> </Grid> (中略) </Grid> </Window>

MainWindow.xaml.cs

C#

1using System; 2using System.Collections.Generic; 3using System.Linq; 4using System.Text; 5using System.Threading.Tasks; 6using System.Windows; 7using System.Windows.Controls; 8using System.Windows.Data; 9using System.Windows.Documents; 10using System.Windows.Input; 11using System.Windows.Media; 12using System.Windows.Media.Imaging; 13using System.Windows.Navigation; 14using System.Windows.Shapes; 15 16namespace Kuro 17{ 18 /// <summary> 19 /// MainWindow.xaml の相互作用ロジック 20 /// </summary> 21 public partial class MainWindow : Window 22 { 23 public MainWindow() 24 { 25 InitializeComponent(); 26 27 } 28 29 /// <summary> 30 /// キャラ名編集 31 /// </summary> 32 /// <param name="sender"></param> 33 /// <param name="e"></param> 34 public void CName_Edit(object sender, RoutedEventArgs e) 35 { 36 37 //キャラ名入力 38 string CName = Microsoft.VisualBasic.Interaction.InputBox("", "キャラ名入力", Chara1.Text, -1, -1); 39 Chara1.Text = CName; //ここでChara2以降にも代入したい 40 } 41 } 42} 43

試したこと

  • foreach(var child in LogicalTreeHelper.GetChildren(this))でTextBlockを取得し、InputBoxに入力した物を代入しようとした
  • コンテキストメニューの親Gridを取得し、その子コントロールとしてTextBlockを生成しようとした(知識不足で断念)

補足情報(FW/ツールのバージョンなど)

Microsoft Visual Studio Community 2017 version 15.9.5
Microsoft .NET Framework version 4.7.03056

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Gurz1019_MP

2019/01/14 13:43

常時入力可能では問題がありますか?
kiyure

2019/01/14 13:53

同じ要領で時刻の記録と計算を行おうと思っているので、できればそれは避けたいです。 (質問文から完全に抜けていました、すみません)
Gurz1019_MP

2019/01/15 13:51

TextBoxを避けたい理由をもう少し詳しく教えてください。現状の要求ですとTextBoxで対応可能なように思います。
kiyure

2019/01/15 23:26

本文を編集した時点で大きな勘違いをしていて、それを直さずそのままにしていたようです。 度々申し訳ありません。
guest

回答2

0

ベストアンサー

キャラ名を表示しているTextBlockをTextBoxに変更し、コンテキストメニューを押した時にこれのIsReadOnlyを変更することで実現可能だと思います。またXamlを見た所、同じパターンのUIが並ぶような構造になっていますが、こういったUIはItemsControl系のコントロールを使うことで一定のテンプレートを繰り返し適用できます。
サンプルコードを載せます。MVVMに関してはこちらの質問も参考にしてください。MVVMでModelを使いたい。

XAML

1<Window x:Class="WpfApp3.MainWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 5 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 6 xmlns:local="clr-namespace:WpfApp3" 7 xmlns:vm="clr-namespace:WpfApp3.ViewModel" 8 xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" 9 mc:Ignorable="d" 10 Title="MainWindow" Height="450" Width="800"> 11 12 <Window.DataContext> 13 <vm:MainWindowViewModel/> 14 </Window.DataContext> 15 16 <Grid> 17 <ListBox ItemsSource="{Binding Characters}" VerticalAlignment="Top"> 18 <ListBox.ItemsPanel> 19 <ItemsPanelTemplate> 20 <StackPanel Orientation="Horizontal"/> 21 </ItemsPanelTemplate> 22 </ListBox.ItemsPanel> 23 <ListBox.ItemTemplate> 24 <DataTemplate DataType="{x:Type vm:Character}"> 25 <Grid Width="100"> 26 <Grid.RowDefinitions> 27 <RowDefinition Height="Auto"/> 28 <RowDefinition Height="Auto"/> 29 </Grid.RowDefinitions> 30 <TextBlock Text="{Binding Header}" HorizontalAlignment="Center"/> 31 <Grid Grid.Row="1"> 32 <Border BorderBrush="Black" BorderThickness="1" Height="18"> 33 <Border.ContextMenu> 34 <ContextMenu> 35 <MenuItem Header="キャラ名編集" Command="{Binding StartEditNameCommand}"/> 36 </ContextMenu> 37 </Border.ContextMenu> 38 <TextBox Text="{Binding Name}" 39 HorizontalContentAlignment="Center" 40 IsReadOnly ="{Binding IsNameReadOnly}"> 41 <i:Interaction.Triggers> 42 <i:EventTrigger EventName="LostFocus"> 43 <i:InvokeCommandAction Command="{Binding EndEditNameCommand}"/> 44 </i:EventTrigger> 45 </i:Interaction.Triggers> 46 </TextBox> 47 </Border> 48 </Grid> 49 </Grid> 50 </DataTemplate> 51 </ListBox.ItemTemplate> 52 </ListBox> 53 </Grid> 54</Window> 55

C#

1using System.Collections.ObjectModel; 2using WpfApp3.Common; 3 4namespace WpfApp3.ViewModel 5{ 6 class MainWindowViewModel : NotificationObject 7 { 8 public MainWindowViewModel() 9 { 10 Characters = new ObservableCollection<Character>() 11 { 12 new Character() { Header = "Sun", Name = "キャラ1" }, 13 new Character() { Header = "Mon", Name = "キャラ2" } 14 }; 15 } 16 17 private ObservableCollection<Character> _characters; 18 19 public ObservableCollection<Character> Characters 20 { 21 get { return _characters; } 22 set 23 { 24 if (_characters != value) 25 { 26 _characters = value; 27 RaisePropertyChanged(nameof(Characters)); 28 } 29 } 30 } 31 } 32} 33

C#

1using WpfApp3.Common; 2 3namespace WpfApp3.ViewModel 4{ 5 public class Character : NotificationObject 6 { 7 #region Header変更通知プロパティ 8 9 private string _header; 10 11 public string Header 12 { 13 get { return _header; } 14 set 15 { 16 if (_header != value) 17 { 18 _header = value; 19 RaisePropertyChanged(nameof(Header)); 20 } 21 } 22 } 23 24 #endregion 25 26 #region Name変更通知プロパティ 27 28 private string _Name; 29 30 public string Name 31 { 32 get { return _Name; } 33 set 34 { 35 if (_Name != value) 36 { 37 _Name = value; 38 RaisePropertyChanged(Name); 39 } 40 } 41 } 42 43 #endregion 44 45 #region IsNameReadOnly変更通知プロパティ 46 47 private bool _isNameReadOnly = true; 48 49 public bool IsNameReadOnly 50 { 51 get { return _isNameReadOnly; } 52 set 53 { 54 if (_isNameReadOnly != value) 55 { 56 _isNameReadOnly = value; 57 RaisePropertyChanged(nameof(IsNameReadOnly)); 58 } 59 } 60 } 61 62 #endregion 63 64 #region StartEditNameCommandプロパティ 65 66 private DelegateCommand _startEditNameCommand; 67 68 public DelegateCommand StartEditNameCommand 69 { 70 get 71 { 72 if (_startEditNameCommand == null) 73 { 74 _startEditNameCommand = new DelegateCommand(StartEditName); 75 } 76 return _startEditNameCommand; 77 } 78 } 79 80 #endregion 81 82 #region EndEditNameCommandプロパティ 83 84 private DelegateCommand _endEditNameCommand; 85 86 public DelegateCommand EndEditNameCommand 87 { 88 get 89 { 90 if (_endEditNameCommand == null) 91 { 92 _endEditNameCommand = new DelegateCommand(EndEditName); 93 } 94 return _endEditNameCommand; 95 } 96 } 97 98 #endregion 99 100 public void StartEditName() 101 { 102 IsNameReadOnly = false; 103 } 104 105 public void EndEditName() 106 { 107 IsNameReadOnly = true; 108 } 109 } 110} 111

投稿2019/01/14 15:18

Gurz1019_MP

総合スコア196

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Gurz1019_MP

2019/01/14 15:20

長くなりすぎたので追記です。サンプルの実行にはSystem.Windows.Interactivityへの参照設定が必要です。このサンプルでは編集中にテキストボックスがフォーカスを失うと、IsReadOnlyがTrueに戻るようになっています。ItemsControlとしてListBoxを使用しています。MainWindowViewModelのCharactersを増やすと、UIが同じパターンで右に伸びていきます。
kiyure

2019/01/15 23:35 編集

解説と貼っていただいたサンプルコードを参考に、実装ができました。 非常に分かりやすい回答ありがとうございました。
guest

0

単純に、はじめから全部TextBoxでいいのでは。

IsReadOnly IsEnabled を使うと入力の制御が行える。
https://code.msdn.microsoft.com/windowsdesktop/XAML-WPF-201ae943

デフォルトの表示が気に入らないなら、Styleで表示を変えればいいと思う。

投稿2019/01/14 13:53

kiichi54321

総合スコア1984

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kiyure

2019/01/14 14:06

すみません、本文から抜けていた事として、時刻の記録や計算も行いたいのです。
episteme

2019/01/14 18:42

↑くわしく。
kiyure

2019/01/15 23:47

「その時点での時刻を記録し、1週間後の時刻を表示する」という物で、現在Gurz1019_MPさんの回答を元に制作しています。 今回は本筋から外れるため、あまり言及はしませんでした。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問