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

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

ただいまの
回答率

90.61%

  • C#

    6847questions

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

  • WPF

    678questions

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

  • canvas

    251questions

    HTML5の<canvas>要素用のタグです。CanvasはHTML5から導入された、二次元の図形描写が可能な要素です。

WPF Canvasに描いた線だけを消す方法が分かりません。

解決済

回答 3

投稿

  • 評価
  • クリップ 1
  • VIEW 305

gucha

score 32

キャンバスに等間隔に線を引きグリッドの様に背景に表示させておこうとしています。
キャンバスサイズも変更させたいのでサイズを変更する時にグリッドを再描画させています。
しかし再描画する際に線だけを消す方法が分からず線以外の子要素も消えてしまいます。

MainWindow.xaml

    <Grid>
        <ScrollViewer HorizontalAlignment="Stretch" HorizontalScrollBarVisibility="Auto"
                          VerticalScrollBarVisibility="Auto" VerticalAlignment="Stretch" Margin="0,0,0,235">
            <Canvas Name="gridCanvas" Background="#FF444444" Width="500" Height="70" SnapsToDevicePixels="True" HorizontalAlignment="Left" Margin="0,0,0,249">
                <Thumb Canvas.Top ="5" Canvas.Left="5" Width="30" Height="30" Name="thmub" />
                <StackPanel Canvas.Top="5" Canvas.Left="40" Width="30" Height="30" Background="#FFE66262"/>
            </Canvas>
        </ScrollViewer>
        <Slider Name="slider" HorizontalAlignment="Left" Margin="10,105,0,0" VerticalAlignment="Top" Width="490" ValueChanged="Slider_ValueChanged"/>
    </Grid>


キャンバスには色付けしたThumbとStackPanelを配置してあります。
スライダーでキャンバスサイズを変更します。
イメージ説明

MainWindow.xaml.cs

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            CreateGridView(500);
        }

        //スライダー変更でキャンバスのサイズ変更
        private void Slider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            int width = 500 + (int)slider.Value * 5;
            gridCanvas.Width = width;
            //グリッドの再描画
            CreateGridView(width);
        }

        //グリッドの描画
        private void CreateGridView(int gw)
        {
            //線だけ消す方法が分かりません。
            //ThumbやStackPanelも線の上に表示させたいです。
            gridCanvas.Children.Clear();
            int GRID_SIZE_W = gw; //横上限
            int GRID_SIZE_H = 70; //縦上限
            int span_W = gw / 10; //横間隔
            int span_H = 70 / 3; //縦間隔

            //縦線
            for (int i = 0; i < GRID_SIZE_W; i += span_W)
            {
                gridCanvas.Children.Add(new Line()
                {
                    X1 = i,
                    Y1 = 0,
                    X2 = i,
                    Y2 = GRID_SIZE_H,
                    Stroke = Brushes.LightGray,
                    StrokeThickness = 2,
                });
            }

            //横線
            for (int i = 0; i < GRID_SIZE_H; i += span_H)
            {
                gridCanvas.Children.Add(new Line()
                {
                    X1 = 0,
                    Y1 = i,
                    X2 = GRID_SIZE_W,
                    Y2 = i,
                    Stroke = Brushes.LightGray,
                    StrokeThickness = 2,
                });
            }
        }
    }

gridCanvas.Children.Clear();で前に描画されたグリッドを全て消しているのですが、その際に子要素も消えてしまいます。
これを線だけを消すようにしたいのですが方法が分からないので教えてください。
あとChildre.Clear()で消さない場合もThumbとStackPanelが線の後ろ側に表示されるのも解決したいです。
線だけを別のキャンバスに描くような方法はあるのでしょうか?

よろしくお願いします。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

checkベストアンサー

+1

追加したLINEを別のところで保持しておいて、それを消しに行くとか言う方法もあるけど、
Canvasを複数用意するのが簡単じゃないかな。

<ScrollViewer>
   <Canvas Name="gridCanvas"/>
   <Canvas Name="gridCanvas2"/>
</ScrollViewer>

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/05/01 20:09

    xamlに記述したところ
    プロパティContentは1回しか設定できません。
    とエラーが出ました・・・。

    キャンセル

  • 2018/05/01 21:27

    以下のように、ScrollViewerのContentひとつのCanvasにしてしまって、その中で2つ持たせれば良いです。
    <ScrollViewer>
     <Canvas Name”parentCanvas”>
    <Canvas Name="gridCanvas"/>
    <Canvas Name="gridCanvas2"/>
    </Canvas>
    </ScrollViewer>

    キャンセル

  • 2018/05/01 22:45

    dodox86さん
    コードをxamlに書いた時点では同じように警告が出ていましたが無視して開始したところエラーは消えました。
    動作も期待通りの結果が得られましたのでこちらをベストアンサーとさせて頂きます。
    お二人ともありがとうございました。

    キャンセル

+1

これを線だけを消すようにしたいのですが方法が分からないので教えてください。

線(Line)だけを消す方法としては、gridCanvasChildrenプロパティがUIElementCollectionクラスなので、そのクラスメソッドであるRemoveRemoveAtを使うことで削除することができます。
UIElementCollection クラス

ですが、Lineのみを削除後、座標を再計算したLineを追加するとThumbStackPanelの位置関係が意図したものにしづらいので、全削除 --> 再計算したLineを追加 --> 元のThumbとStackPanelを追加 との流れの方が良いでしょう。そうすることでご要望のかたちにはなります。

以下は、そのように直してみたClearGridView2です。差し替えて試してみてください。

        private void ClearGridView2(int gw)
        {
            //線だけ消す方法が分かりません。
            //ThumbやStackPanelも線の上に表示させたいです。
            //            gridCanvas.Children.Clear();

            int GRID_SIZE_W = gw; //横上限
            int GRID_SIZE_H = 70; //縦上限
            int span_W = gw / 10; //横間隔
            int span_H = 70 / 3; //縦間隔

            List<UIElement> keepElems = new List<UIElement>();
            foreach (UIElement elem in gridCanvas.Children)
            {
                // UIElementがLineかどうか判定
                if (elem.GetType() == typeof(Line))
                {
                    ; // Line
                }
                else
                {
                    // Line以外を保存(ThumbとStackPanel)
                    keepElems.Add(elem);
                }
            }

            // いったん全部クリア
            gridCanvas.Children.Clear();

            //縦線
            for (int i = 0; i < GRID_SIZE_W; i += span_W)
            {
                gridCanvas.Children.Add(new Line()
                {
                    X1 = i,
                    Y1 = 0,
                    X2 = i,
                    Y2 = GRID_SIZE_H,
                    Stroke = Brushes.LightGray,
                    StrokeThickness = 2,
                });
            }

            //横線
            for (int i = 0; i < GRID_SIZE_H; i += span_H)
            {
                gridCanvas.Children.Add(new Line()
                {
                    X1 = 0,
                    Y1 = i,
                    X2 = GRID_SIZE_W,
                    Y2 = i,
                    Stroke = Brushes.LightGray,
                    StrokeThickness = 2,
                });
            }

            // ThumbとStackPanelを追加
            foreach (UIElement elem in keepElems)
            {
                gridCanvas.Children.Add(elem);
            }
        }
    }

ご質問の直接の回答としては以上ですが、質問者さんが本当にやりたいことへの解法としては、この方法よりは先の回答者さんの「Canvasを2つ使う」方法に賛同します。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/05/01 22:45

    新しいリストへ格納しておく方法があったのですね!
    ご指摘の通りCanvasを2つ使う方法を今回は採用させて頂きましたが、この方法も勉強になりました。
    複数の方法を教えて頂きありがとうございました。

    キャンセル

+1

参考までに、等間隔の線の描画は XAML だけでも可能です。
ミソは TileMode です。

<Canvas>
  <Canvas.Background>
    <VisualBrush TileMode="Tile"
                  Viewport="0,0,50,50"
                  ViewportUnits="Absolute">
      <VisualBrush.Visual>
        <Border BorderThickness="0,0,1,1"
                BorderBrush="Black"
                Width="50"
                Height="50" />
      </VisualBrush.Visual>
    </VisualBrush>
  </Canvas.Background>
</Canvas>

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/05/02 14:57

    こちらの方法も意図している動作を確認しました。
    教えて頂きありがとうございます。
    線に細かく細工をしないのであればこちらの方が手軽で良さそうです。

    キャンセル

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

  • ただいまの回答率 90.61%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • C#

    6847questions

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

  • WPF

    678questions

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

  • canvas

    251questions

    HTML5の<canvas>要素用のタグです。CanvasはHTML5から導入された、二次元の図形描写が可能な要素です。